Documentation
¶
Index ¶
- Constants
- Variables
- func ActiveUsersForNodeQuery(db *gorm.DB, groupID *uint, now time.Time) *gorm.DB
- func AdminUserResetRequestID(kind string, userID uint, token string) string
- func AdvancePackageCohort(db *gorm.DB, generationID uint, target uint8) (*model.PackageRouteGeneration, error)
- func AllocateNodeOperationRevision(db *gorm.DB, nodeID uint, floor int64) (int64, error)
- func AmountPaysOrder(amount float64, totalCents int64) bool
- func ApplyTopologyObservedStateTx(tx *gorm.DB, update TopologyObservedStateUpdate) (*model.TopologyObservedState, bool, error)
- func AuditUsername(db *gorm.DB, userID *uint) string
- func BackfillForwardPortBindings(db *gorm.DB) error
- func BackupConfigAuditContent(cfg *model.BackupConfig, preservedSensitiveFields []string) string
- func BeginPackageMigration(db *gorm.DB, input model.PackageMigrationRun) (*model.PackageMigrationRun, error)
- func BootstrapIdentityPlatformPackage(db *gorm.DB, encodedPublicKey, directory string) error
- func BuildAgentPluginInstallConfig(db *gorm.DB, nodeID uint, pluginID, version string) (string, error)
- func BuildLoginRateLimitKey(email, ip string) string
- func BuildNodeProtocolConfig(node *model.Node, protocol *model.NodeProtocol) map[string]any
- func BuildRegisterRateLimitKey(ip string) string
- func BuildUniProxyNodeConfig(db *gorm.DB, nodeID uint, preferredType string) (map[string]any, error)
- func BumpSettingsGeneration(namespace string) uint64
- func BumpSettingsGenerationAfter(namespace string, before uint64) (uint64, bool)
- func CancelKernelOperation(db *gorm.DB, operationID string, at time.Time) (*model.KernelOperation, error)
- func CanonicalKernelOperationConfig(raw string) (string, error)
- func CanonicalPluginManifest(manifest PluginManifest) ([]byte, error)
- func CreateKernelOperation(db *gorm.DB, operation model.KernelOperation) (*model.KernelOperation, bool, error)
- func CreateTopologyRevision(db *gorm.DB, topologyID, actorID uint, input TopologyRevisionInput) (*model.TopologyRevision, error)
- func DecodeRawNodeConfig(raw any) (map[string]any, []byte, error)
- func DefaultBackupConfig() model.BackupConfig
- func DeleteUserTx(tx *gorm.DB, id uint) (authn.Revocation, error)
- func DeriveSS2022ServerKey(createdAt time.Time, cipher string) string
- func DropNodeCache(id uint)
- func EnsureAgentDiagnosticTaskSchema(db *gorm.DB) error
- func EnsureForwardBridgeSchema(db *gorm.DB) error
- func EnsureForwardNodeMetricsPortColumn(db *gorm.DB) error
- func EnsureForwardPortBindingSchema(db *gorm.DB) error
- func EnsureForwardRuntimeJobSchema(db *gorm.DB) error
- func EnsureKernelSchema(db *gorm.DB) error
- func EnsureNodeRuntimeHealthSchema(db *gorm.DB) error
- func EnsureObservabilitySchema(db *gorm.DB) error
- func EnsurePluginTrustRoot(db *gorm.DB, publicKey ed25519.PublicKey) (*model.PluginTrustRoot, error)
- func EnsureStatsSchema(db *gorm.DB) error
- func EnsureWireGuardPeerSchema(db *gorm.DB) error
- func ExpireKernelOperations(db *gorm.DB, now time.Time) (int64, error)
- func ExtractPluginWebUIBundle(manifest PluginManifest, artifact []byte) ([]byte, error)
- func ForwardNodeAPIToken(db *gorm.DB, node *model.ForwardNode) (string, error)
- func ForwardNodeHasToken(db *gorm.DB, nodeID uint) (bool, error)
- func ForwardUserResetRequestID(userID uint, token string) string
- func GenerateForwardNodeToken() (string, error)
- func GenerateWireGuardKeypair() (privateKey string, publicKey string, err error)
- func GetPluginArtifact(db *gorm.DB, releaseID uint) (*model.PluginArtifact, error)
- func GetPluginConfiguration(db *gorm.DB, installationID uint) (*model.PluginConfiguration, error)
- func HashKernelOperationConfig(raw string) (string, error)
- func IdentityAuthoritative(state string) bool
- func IdentityAuthorityState(db *gorm.DB) (string, error)
- func InitAdmin(cfg *config.Config) error
- func InitDefaultAuthKeyFromEnv()
- func InitDefaultPlan()
- func InitForwardRuntimeSystemConfig(db *gorm.DB) error
- func InitSubscriptionDefaults()
- func InviteCodeLockKeys(userID uint) (int32, int32)
- func IsAgentPluginOperation(kind string) bool
- func IsForwardDiagnosticCheck(action string) bool
- func IsNodeSecretKey(key string) bool
- func IsSensitiveSystemConfigKey(key string) bool
- func IsSuperAdmin(db *gorm.DB, userID uint) (bool, error)
- func IsWireGuardExitProtocol(protocol *model.NodeProtocol) bool
- func IssueForwardNodeTokenTx(tx *gorm.DB, nodeID uint, token string) (bool, error)
- func IssueProxyNodeCredentialsTx(tx *gorm.DB, nodeID uint, credentials ProxyNodeCredentials, replaced bool) error
- func IssueRegistrationKeyTx(tx *gorm.DB, name string, expireAt *int64) (*model.AuthorizedKey, string, error)
- func KeepNodeRawConfig(incoming string, stored *string) string
- func KeepNodeSecretsJSON(incoming, stored string) string
- func KeepSystemConfigFields(key, incoming, stored string) (value string, kept bool)
- func LegacyTopologyObservedHealthJSON() string
- func LoadBackupConfig(db *gorm.DB) (*model.BackupConfig, error)
- func LoadVerifiedPluginCompatibilityRoutes(db *gorm.DB, release model.PluginRelease, publicKey ed25519.PublicKey) ([]byte, error)
- func LoadVerifiedPluginWebUIAsset(db *gorm.DB, release model.PluginRelease, manifest PluginManifest) (*model.PluginWebUIAsset, error)
- func LockNodePluginLifecycleTx(tx *gorm.DB, nodeID uint, pluginID string) (*model.NodePluginLifecycle, error)
- func LockPluginInstallationTarget(tx *gorm.DB, target string) error
- func LockUserInviteCodes(tx *gorm.DB, userID uint) error
- func MaskAuthorizedKeys(keys []model.AuthorizedKey)
- func MaskSystemConfigFields(key, value string) string
- func MaskSystemConfigValue(key, value string) (displayValue string, sensitive bool, hasValue bool)
- func MaterializePluginControlArtifact(db *gorm.DB, publicKey ed25519.PublicKey, ...) (pluginhost.ArtifactRef, error)
- func MigratePackageHost(ctx context.Context, db *gorm.DB, manager *pluginhost.Supervisor, ...) (pluginhost.MigrationOutput, error)
- func NewSubscriberUser(email, passwordHash string) *model.User
- func NodeHeartbeatStatus() clause.Expr
- func NodeOpsCapabilities() []string
- func NodeTrafficBucketBounds(granularity string, since, until, now time.Time) (time.Time, time.Time, error)
- func NormalizeForwardRuntimeBackend(value string) (string, bool)
- func NormalizeNodeLogLevel(level string) string
- func NormalizeNodeType(nodeType string) string
- func OrderPaymentRequestID(tradeNo string) string
- func PackageIndexMigrationID(indexSHA256 string) string
- func PackageMigrationStepsDigest(steps []pluginhost.MigrationStep) string
- func PackageReleaseAtLeast(version, minimum string) bool
- func PackageReportRefusal(err error) string
- func PackageReportStale(kind string, observedAt, now time.Time) bool
- func PackageRouteCatalog() (map[string]RouteCatalogEntry, error)
- func PackageRouteDefaultPolicy() string
- func PackageRouteDefaultsSummary() (string, error)
- func ParseOfficialPluginPublicKey(encoded string) (ed25519.PublicKey, error)
- func ParseOnlineData(data map[string]any) (map[uint][]string, error)
- func ParsePluginMigrationIndex(manifest PluginManifest, artifact []byte) ([]pluginhost.MigrationStep, error)
- func ParseTrafficData(data map[string]any) (map[uint][2]int64, error)
- func PlanAssignmentRequestID(planID, userID uint, expireAt *int64, token string) string
- func PlanTopologyDeployment(db *gorm.DB, input TopologyDeploymentPlanInput) (*model.TopologyDeployment, []model.TopologyDeploymentStep, error)
- func PluginAPIPermission(pluginID string) string
- func PluginArtifactStorageKey(pluginID, version, artifactSHA256 string) string
- func PluginControlBridgeRouteID(pluginID, route string) string
- func PluginRuntimeIsRemote(db *gorm.DB) func(context.Context, string) (bool, error)
- func PluginRuntimeOf(ctx context.Context, db *gorm.DB, pluginID string) (string, error)
- func PluginTrustRootFingerprint(publicKey ed25519.PublicKey) string
- func PluginTrustRootKeyID(publicKey ed25519.PublicKey) string
- func PluginWebUIAssetStorageKey(pluginID, version, bundleSHA256, bundlePath string) string
- func PluginWebUIAssetURL(pluginID, version, bundleSHA256, bundlePath string) string
- func ProxyNodeHasCredentials(db *gorm.DB, nodeID uint) (apiKey, secret bool, err error)
- func PurgeCompletedAssignmentDeletes(tx *gorm.DB, lifecycle *model.NodePluginLifecycle, ...) error
- func RaiseNodeOperationRevision(db *gorm.DB, nodeID uint, revision int64) error
- func ReconcileAgentAssignments(db *gorm.DB, now time.Time) (int, error)
- func RecordMigrationCheckpoint(db *gorm.DB, migrationRunID uint, checkpoint PackageMigrationCheckpoint) (*model.PackageMigrationRun, error)
- func RecordNodePluginOperationSuccessTx(tx *gorm.DB, operation model.KernelOperation) error
- func RecordPackageValidation(db *gorm.DB, input model.PackageValidationResult) (*model.PackageValidationResult, error)
- func RedactNode(node *model.Node)
- func RedactNodeProtocol(protocol *model.NodeProtocol)
- func RedactNodeProtocols(protocols []model.NodeProtocol)
- func RedactNodeSecretsJSON(config string) string
- func RefreshAgentPluginInstallationObservedState(db *gorm.DB, pluginID string) error
- func RegisterPluginRelease(db *gorm.DB, manifestJSON, signature string, publicKey ed25519.PublicKey) (*model.PluginRelease, error)
- func RenumberPendingNodeOperations(db *gorm.DB, nodeID uint, operationID string, floor int64) (int64, error)
- func ReportNodeSecretFindings(findings []NodeSecretFinding)
- func RequestTopologyDeploymentApply(db *gorm.DB, deploymentID uint, _ time.Time) (*model.TopologyDeployment, error)
- func RequestTopologyDeploymentRollback(db *gorm.DB, deploymentID uint, at time.Time) (*model.TopologyDeployment, error)
- func ResetLoginRateLimiterForTest()
- func ResetStatsServiceForTest()
- func ResolveActivePluginWebUIAsset(db *gorm.DB, publicKey ed25519.PublicKey, actorID uint, legacyAdmin bool, ...) (*model.PluginWebUIAsset, error)
- func ResolveEffectivePackageRouteModes(db *gorm.DB, packageID, version string, stored map[string]string) (map[string]string, map[string]string, error)
- func ResolvePackageRouteModes(db *gorm.DB, packageID string, stored map[string]string) (map[string]string, error)
- func RevokeCleanAgentTx(tx *gorm.DB, id uint) error
- func RevokeRegistrationKeyTx(tx *gorm.DB, id uint) (bool, error)
- func RollbackPackageGeneration(db *gorm.DB, generationID uint, reason string) (*model.PackageRouteGeneration, error)
- func RouteModeActorName(db *gorm.DB, userID uint) string
- func RunForwardRuntimeJobPayloadScrub(ctx context.Context, db *gorm.DB)
- func ScrubForwardRuntimeJobPayload(payload string) (string, bool)
- func ScrubForwardRuntimeJobPayloads(ctx context.Context, db *gorm.DB, batch int) (int64, error)
- func SetPackageRouteDefaultPolicy(policy string)
- func SetPackageRouteModesTx(tx *gorm.DB, publicKey ed25519.PublicKey, installationID uint, ...) (*model.PluginConfiguration, error)
- func SetPluginRuntime(ctx context.Context, db *gorm.DB, pluginID, runtime string, remoteEnabled bool, ...) (*model.PluginRuntime, error)
- func SettingsCapability(namespace, access string) string
- func SettingsGeneration(namespace string) uint64
- func ShadowSampleRoute(routeID string) (shadowsamples.RouteInfo, bool)
- func StorePluginArtifact(db *gorm.DB, releaseID uint, artifact []byte) (*model.PluginArtifact, error)
- func StringifyConfigMap(m map[string]any) map[string]string
- func SubscriptionGroupDeleteRequestID(groupID uint, token string) string
- func SubscriptionGroupGrantRequestID(userID, groupID uint, expireAt, transferEnable, nextRenewPrice *int64, ...) string
- func SubscriptionGroupRevokeRequestID(userID, groupID uint, token string) string
- func SubscriptionResetRateLimitKey(userID uint) string
- func SyncAgentInstallationAssignments(tx *gorm.DB, installation model.PluginInstallation, configRevision int64, ...) ([]*model.KernelOperation, error)
- func SyncNodePluginLifecycle(tx *gorm.DB, nodeID uint, pluginID string, explicitRetry bool, _ time.Time) (*model.NodePluginLifecycle, bool, error)
- func SystemConfigAuditContent(cfg *model.SystemConfig, preserveExisting bool) string
- func SystemConfigMaskedFields(key string) []string
- func TelegramWebhookSecret(token string) string
- func TouchSettingsKey(key string)
- func UpdatePluginConfigurationWithValidatorAndHook(db *gorm.DB, publicKey ed25519.PublicKey, installationID uint, ...) (*model.PluginConfiguration, error)
- func UpdateUserOnceTx(tx *gorm.DB, requestID, method string, userID uint, updates map[string]any, ...) (bool, *authn.Revocation, error)
- func UpdateUserTx(tx *gorm.DB, id uint, updates map[string]any) (*authn.Revocation, error)
- func UpdateUserTxWithTokenVersion(tx *gorm.DB, id uint, updates map[string]any, tokenVersion uint64) (*authn.Revocation, error)
- func UserAliveCounts() (map[uint64]int, error)
- func UserSubscriptionResetRequestID(userID uint, token string) string
- func ValidateAgentDiagnosticTask(action string, params map[string]any) (map[string]any, error)
- func ValidateForwardDiagnosticCheck(action string, params map[string]any) (map[string]any, error)
- func ValidateNodeProtocol(protocol *model.NodeProtocol) error
- func ValidatePluginAPIGrantPermissions(pluginID, raw string) error
- func ValidatePluginDependencyExecutionPlan(db *gorm.DB, plan *PluginDependencyExecutionPlan) error
- func ValidatePluginInstallationPlan(db *gorm.DB, release model.PluginRelease, target string, enabled bool, ...) error
- func ValidatePluginReleaseTarget(release model.PluginRelease, target string) error
- func ValidateRegistrationEmail(email string, policy RegistrationPolicy) error
- func ValidateTrafficDelta(upload, download int64) error
- func ValidateWireGuardRuntimeConfig(config map[string]any) error
- func VerifyPluginArtifact(manifest PluginManifest, artifact []byte) error
- func WithAgentLifecycleTransaction(db *gorm.DB, mutation func(*gorm.DB) error) error
- func WithRetryableTransaction(db *gorm.DB, mutation func(*gorm.DB) error) error
- func WithdrawDebitRequestID(withdrawID uint) string
- func WithdrawRefundCents(amount float64) (int64, bool)
- func WithdrawRefundRequestID(withdrawID uint) string
- type ActorPluginAccess
- func (access ActorPluginAccess) Allows(pluginID, permission string) bool
- func (access ActorPluginAccess) HasAnyPermission(pluginID string) bool
- func (access ActorPluginAccess) PermissionMode() string
- func (access ActorPluginAccess) ProfilePermissions() []string
- func (access ActorPluginAccess) ProfileRestrictedPluginList() []string
- func (access ActorPluginAccess) RestrictedPluginList() []string
- type AgentAssignmentOperationChain
- type AgentDiagnosticActionSpec
- type AgentDiagnosticTaskService
- func (s *AgentDiagnosticTaskService) CompleteTask(taskID string, nodeID uint, action string, success bool, output string, ...) error
- func (s *AgentDiagnosticTaskService) CreateTask(taskID string, nodeID uint, action string, params map[string]any) (*model.AgentDiagnosticTask, error)
- func (s *AgentDiagnosticTaskService) GetTask(taskID string) (*model.AgentDiagnosticTask, error)
- func (s *AgentDiagnosticTaskService) ListTasks(nodeID uint, limit int) ([]model.AgentDiagnosticTask, error)
- func (s *AgentDiagnosticTaskService) MarkStatus(taskID string, status string) error
- func (s *AgentDiagnosticTaskService) PullPendingTasks(nodeID uint) ([]model.AgentDiagnosticTask, error)
- type AgentNodeStatus
- type AgentPluginArtifactAddress
- type AgentPluginInstallConfig
- type AgentPluginManifestAddress
- type AgentPluginReleaseDownload
- type AuthService
- type BackupService
- func (s *BackupService) CleanupOldBackups() error
- func (s *BackupService) CreateBackup(backupType string, createdBy *uint) (*model.BackupRecord, error)
- func (s *BackupService) DeleteBackup(id uint) error
- func (s *BackupService) GetBackupStats() (map[string]any, error)
- func (s *BackupService) GetConfig() (*model.BackupConfig, error)
- func (s *BackupService) ListBackups(page, pageSize int) ([]model.BackupRecord, int64, error)
- func (s *BackupService) RestoreBackup(id uint) error
- func (s *BackupService) UpdateConfig(cfg *model.BackupConfig) error
- type CreateOrderParams
- type CreateRuleRequest
- type DashboardStats
- type DiagnosisOutcome
- type DiagnosisProbes
- type DiagnosisReport
- type EffectiveAccess
- type EndpointCheck
- type ForwardAgentBridgeService
- type ForwardAgentBridgeWorker
- type ForwardAnsibleStatsWorker
- type ForwardCleanAgentAction
- type ForwardCleanAgentCreateInput
- type ForwardCleanAgentHeartbeatInput
- type ForwardCleanAgentRegisterInput
- type ForwardCleanAgentReportInput
- type ForwardCleanAgentService
- func (s *ForwardCleanAgentService) Heartbeat(input ForwardCleanAgentHeartbeatInput) ([]ForwardCleanAgentAction, error)
- func (s *ForwardCleanAgentService) Register(input ForwardCleanAgentRegisterInput) (*model.ForwardCleanAgent, error)
- func (s *ForwardCleanAgentService) Report(input ForwardCleanAgentReportInput) error
- type ForwardCleanAgentTokenResult
- type ForwardFlowResetWorker
- type ForwardGostStatsWorker
- type ForwardLatencyProber
- type ForwardNodeService
- func (s *ForwardNodeService) CheckEndpoint(ctx context.Context, probes DiagnosisProbes, nodeID uint, record bool) (*HealthCheckResult, error)
- func (s *ForwardNodeService) CheckEndpoints(ctx context.Context, probes DiagnosisProbes, nodeIDs []uint, record bool) ([]EndpointCheck, error)
- func (s *ForwardNodeService) Create(node *model.ForwardNode) error
- func (s *ForwardNodeService) Delete(id uint) error
- func (s *ForwardNodeService) GenerateAPIToken() (string, error)
- func (s *ForwardNodeService) GetByID(id uint) (*model.ForwardNode, error)
- func (s *ForwardNodeService) GetByIDForInventoryScope(id uint, scope string) (*model.ForwardNode, error)
- func (s *ForwardNodeService) GetByType(nodeType string) ([]*model.ForwardNode, error)
- func (s *ForwardNodeService) HealthCheck(ctx context.Context, nodeID uint) (*HealthCheckResult, error)
- func (s *ForwardNodeService) ListByInventoryScope(scope, nodeType string, status *int, page, pageSize int) ([]*model.ForwardNode, int64, error)
- func (s *ForwardNodeService) RecordHealthCheck(node *model.ForwardNode, result *HealthCheckResult) error
- func (s *ForwardNodeService) Update(node *model.ForwardNode) error
- type ForwardNodeTraffic
- type ForwardObservabilityService
- type ForwardRuleService
- type ForwardRuntimeOutcome
- type ForwardRuntimeProvider
- type GroupMember
- type GroupMembersParams
- type GroupMembersResult
- type GroupStats
- type HealthCheckResult
- type HourlyTraffic
- type InviteCodeListQuery
- type InviteService
- func (s *InviteService) AddCommission(userID, orderID, fromUserID uint, amount float64, recordType int, ...) error
- func (s *InviteService) CalculateCommission(orderAmount float64) float64
- func (s *InviteService) GenerateAdminInviteCodes(count int, expireDays *int, now time.Time) ([]model.InviteCode, error)
- func (s *InviteService) GenerateInviteCode(userID *uint) (*model.InviteCode, error)
- func (s *InviteService) GenerateUserInviteCode(userID uint) (*model.InviteCode, error)
- func (s *InviteService) GetCommissionRecords(userID uint, page, pageSize int) ([]model.CommissionRecord, int64, error)
- func (s *InviteService) GetConfig() (*model.InviteConfig, error)
- func (s *InviteService) GetInviteStats(userID uint) (map[string]any, error)
- func (s *InviteService) GetUserInviteCodes(userID uint) ([]model.InviteCode, error)
- func (s *InviteService) GetWithdrawRecords(userID uint, page, pageSize int) ([]model.CommissionWithdraw, int64, error)
- func (s *InviteService) ListInviteCodes(query InviteCodeListQuery, now time.Time) ([]model.InviteCode, int64, error)
- func (s *InviteService) ProcessWithdraw(withdraw *model.CommissionWithdraw, status int, remark string, now time.Time) error
- func (s *InviteService) RequestWithdraw(userID uint, amount float64, method, account, name string) (*model.CommissionWithdraw, error)
- func (s *InviteService) RevokeInviteCode(id uint) error
- func (s *InviteService) SaveConfig(cfg *model.InviteConfig) error
- func (s *InviteService) SetConfig(cfg *model.InviteConfig)
- type KernelOperationStatus
- type LatencyPoint
- type LatencyTrend
- type LegacyForwardAnsibleCleaner
- type LegacyForwardNodeXCleaner
- type LoadBalancerService
- func (s *LoadBalancerService) Create(lb *model.LoadBalancer) error
- func (s *LoadBalancerService) Delete(id uint) error
- func (s *LoadBalancerService) GetByID(id uint) (*model.LoadBalancer, error)
- func (s *LoadBalancerService) GetStats(lbID uint) (map[string]any, error)
- func (s *LoadBalancerService) List(groupID uint) ([]model.LoadBalancer, error)
- func (s *LoadBalancerService) RunHealthCheck(lbID uint) error
- func (s *LoadBalancerService) SelectNode(lbID uint) (*model.ForwardNode, error)
- func (s *LoadBalancerService) Update(lb *model.LoadBalancer) error
- type LoginRateLimitOptions
- type LoginRateLimiter
- type MFAService
- func (s *MFAService) CheckBruteForce(userID uint, maxAttempts int, window time.Duration) (bool, error)
- func (s *MFAService) DisableMFA(userID uint, password string) error
- func (s *MFAService) EnableTOTP(userID uint, code string) error
- func (s *MFAService) GetRemainingBackupCodes(userID uint) (int, error)
- func (s *MFAService) GetUserMFA(userID uint) (*model.UserMFA, error)
- func (s *MFAService) IsEnforcedForUser(user *model.User) bool
- func (s *MFAService) RecordLoginAttempt(userID uint, ip, userAgent string, success bool, method string) error
- func (s *MFAService) RegenerateBackupCodes(userID uint) ([]string, error)
- func (s *MFAService) SetConfig(config *model.MFAConfig)
- func (s *MFAService) SetupTOTP(userID uint, email string) (*TOTPSetup, error)
- func (s *MFAService) Verify(userID uint, code, method string) (bool, error)
- func (s *MFAService) VerifyBackupCode(mfa *model.UserMFA, code string) (bool, error)
- func (s *MFAService) VerifyTOTP(secret, code string) bool
- type MultiIngressRow
- type NodeListParams
- type NodeListResult
- type NodeLogInput
- type NodeLogListParams
- type NodeLogListResult
- type NodeLogService
- func (s *NodeLogService) GetLogs(params NodeLogListParams) (*NodeLogListResult, error)
- func (s *NodeLogService) RecordAgentLogBatch(nodeKind string, nodeID uint, batchID string, inputs []NodeLogInput) (bool, error)
- func (s *NodeLogService) RecordAgentMaintenanceEvent(nodeKind string, nodeID uint, event agentcontrol.MaintenanceEvent) (bool, error)
- func (s *NodeLogService) RecordLogs(nodeID uint, inputs []NodeLogInput) error
- func (s *NodeLogService) RecordLogsTx(tx *gorm.DB, nodeID uint, inputs []NodeLogInput) error
- type NodeMonthlyResetWorker
- type NodePluginObservedSnapshot
- type NodePluginRuleCounter
- type NodeSecretFinding
- type NodeSecretValidation
- type NodeService
- func (s *NodeService) AccumulateTrafficOnly(nodeID uint, upload, download int64) error
- func (s *NodeService) AssignProtocolsToGroup(groupID uint, protocolIDs []uint) error
- func (s *NodeService) BuildUniProxyConfig(nodeID uint, preferredType string) (map[string]any, error)
- func (s *NodeService) CreateNode(node *model.Node) error
- func (s *NodeService) CreateProtocol(protocol *model.NodeProtocol) error
- func (s *NodeService) DeleteAuthKey(id uint) error
- func (s *NodeService) DeleteNode(id uint) error
- func (s *NodeService) DeleteProtocol(id uint) error
- func (s *NodeService) GenerateAuthKey(name string, expireDays int) (*model.AuthorizedKey, string, error)
- func (s *NodeService) GetAllAvailableProtocols() ([]model.NodeProtocol, error)
- func (s *NodeService) GetAuthKeys() ([]model.AuthorizedKey, error)
- func (s *NodeService) GetNode(id uint) (*model.Node, error)
- func (s *NodeService) GetNodeByAPIKey(apiKey string) (*model.Node, error)
- func (s *NodeService) GetNodeStats() (map[string]any, error)
- func (s *NodeService) GetNodes(params NodeListParams) (*NodeListResult, error)
- func (s *NodeService) GetProtocol(id uint) (*model.NodeProtocol, error)
- func (s *NodeService) GetProtocols(nodeID uint) ([]model.NodeProtocol, error)
- func (s *NodeService) GetProtocolsByGroup(groupID uint) ([]model.NodeProtocol, error)
- func (s *NodeService) Heartbeat(nodeID uint, req *model.NodeHeartbeatRequest) error
- func (s *NodeService) LatestPackageReport(nodeKind string, nodeID uint, pluginID, kind string, now time.Time) (PackageReport, error)
- func (s *NodeService) NodeCredentials(node *model.Node) (apiKey, secret string)
- func (s *NodeService) PrepareNodeRawConfig(node *model.Node)
- func (s *NodeService) RecordAgentNodeStatus(nodeID uint, status AgentNodeStatus) error
- func (s *NodeService) RecordNodePluginObservedStates(nodeID uint, snapshots []NodePluginObservedSnapshot, receivedAt time.Time) (int, error)
- func (s *NodeService) RecordPackageReport(input PackageReportInput, receivedAt time.Time) (bool, error)
- func (s *NodeService) RecordPluginTelemetry(nodeID uint, heartbeatMetrics map[string]float64, receivedAt time.Time) (int, error)
- func (s *NodeService) RegisterNode(req *model.NodeRegisterRequest, clientIP string) (*model.NodeRegisterResponse, error)
- func (s *NodeService) SyncProtocolToNode(nodeID uint) error
- func (s *NodeService) UpdateLastCheckAt(nodeID uint) error
- func (s *NodeService) UpdateNode(id uint, updates map[string]any) error
- func (s *NodeService) UpdateOnlineUsers(nodeID uint, count int) error
- func (s *NodeService) UpdateProtocol(id uint, updates map[string]any) error
- func (s *NodeService) UpdateRuntimeHealth(nodeID uint, healthy bool, message string) error
- type NodeTrafficPoint
- type NodeTrafficSeries
- type NotificationService
- func (s *NotificationService) Broadcast(title, content string) error
- func (s *NotificationService) Drain()
- func (s *NotificationService) NotifyAdministrators(event, title, content string, data map[string]any) error
- func (s *NotificationService) NotifyNodeOffline(node *model.Node) error
- func (s *NotificationService) NotifyOrderPaid(order *model.Order, user *model.User) error
- func (s *NotificationService) NotifyTicketReply(ticket *model.Ticket, replyBy string) error
- func (s *NotificationService) NotifyTrafficLow(user *model.User, percentLeft float64) error
- func (s *NotificationService) NotifyUserExpire(user *model.User, daysLeft int) error
- func (s *NotificationService) Send(userID *uint, notifyType, event, title, content string, data map[string]any) error
- func (s *NotificationService) SendEmail(to, subject, body string) error
- func (s *NotificationService) SetEmailConfig(cfg *model.EmailConfig)
- type OperationLogInput
- type OperationLogService
- type OrderBuyerRef
- type OrderListParams
- type OrderListResult
- type OrderPaymentReconciler
- type OrderPaymentReconciliation
- type OrderPaymentResult
- type OrderPlanRef
- type OrderService
- func (s *OrderService) Cancel(orderID uint) error
- func (s *OrderService) Complete(orderID uint) error
- func (s *OrderService) Create(params CreateOrderParams) (*model.Order, error)
- func (s *OrderService) GetAdminView(id uint) (*OrderView, error)
- func (s *OrderService) GetByID(id uint) (*model.Order, error)
- func (s *OrderService) GetList(params OrderListParams) (*OrderListResult, error)
- func (s *OrderService) GetStats() (map[string]any, error)
- func (s *OrderService) GetUserOrders(userID uint, page, pageSize int) (*OrderListResult, error)
- func (s *OrderService) GetUserView(userID, id uint) (*OrderView, error)
- func (s *OrderService) UpdateStatus(orderID uint, status int) error
- type OrderView
- type PackageHostMigrator
- type PackageHostOperations
- func (o PackageHostOperations) AuthorizeCapability(ctx context.Context, host packagebridge.HostIdentity, capability string) error
- func (o PackageHostOperations) AuthorizeIdentity(ctx context.Context, host packagebridge.HostIdentity) error
- func (o PackageHostOperations) LeaseStorage(ctx context.Context, host packagebridge.HostIdentity) (packagebridge.StorageLease, error)
- func (o PackageHostOperations) PackageConfig(ctx context.Context, host packagebridge.HostIdentity) (packagebridge.PackageConfig, error)
- type PackageMigrationCheckpoint
- type PackageReport
- type PackageReportInput
- type PackageReportRefusedError
- type PackageRouteDefaultPackage
- type PackageRouteDefaultState
- type PackageRouteDefaults
- type PackageRouteModes
- type PackageStorageGrants
- type PanelAdminTunnelItem
- type PanelForwardFlowData
- type PanelForwardInput
- type PanelForwardListItem
- type PanelForwardOrderUpdate
- type PanelForwardRuntimeAttachmentState
- type PanelForwardRuntimeCommandHints
- type PanelForwardRuntimeConfigState
- type PanelForwardRuntimeDoctorSummary
- type PanelForwardRuntimeJobExecutor
- type PanelForwardRuntimeProbe
- type PanelForwardRuntimeReadiness
- type PanelForwardRuntimeService
- func (s *PanelForwardRuntimeService) Apply(ctx context.Context, action string, forward *model.Forward, ...) (*panelForwardRuntimeResult, error)
- func (s *PanelForwardRuntimeService) BackendForForward(forward *model.Forward) (string, error)
- func (s *PanelForwardRuntimeService) DiagnoseLocalOperator(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
- func (s *PanelForwardRuntimeService) DiagnoseNodeXOperator(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
- func (s *PanelForwardRuntimeService) DiagnosePanelRuntime(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
- func (s *PanelForwardRuntimeService) ForwardsToMoveToBackend(targetBackend string) ([]model.Forward, error)
- func (s *PanelForwardRuntimeService) GetLocalOperatorStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
- func (s *PanelForwardRuntimeService) GetNodeXOperatorStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
- func (s *PanelForwardRuntimeService) GetNodeXRuntimeStatus(ctx context.Context) (*nodeXForwardRuntimeStatus, error)
- func (s *PanelForwardRuntimeService) GetPanelRuntimeStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
- func (s *PanelForwardRuntimeService) MarkForwardsPendingForBackend(targetBackend string) (int64, error)
- func (s *PanelForwardRuntimeService) MoveForwardToBackend(forwardID uint, backend string) error
- func (s *PanelForwardRuntimeService) ResolveBackend() (string, error)
- func (s *PanelForwardRuntimeService) SyncForwardsToBackend(targetBackend string) (synced int, failed int, err error)
- type PanelForwardRuntimeStatusSnapshot
- type PanelForwardRuntimeStatusSummary
- type PanelForwardService
- func (s *PanelForwardService) ActiveTunnelForwardIDs(tunnelID uint) ([]uint, error)
- func (s *PanelForwardService) ApplyForwardRuntime(ctx context.Context, record *model.Forward, action string) (*ForwardRuntimeOutcome, error)
- func (s *PanelForwardService) ApplyForwardTrafficSnapshots(records []PanelForwardTrafficSnapshot) error
- func (s *PanelForwardService) AssignUserTunnel(input PanelUserTunnelInput) error
- func (s *PanelForwardService) CreateTunnel(input PanelTunnelInput) (*PanelAdminTunnelItem, error)
- func (s *PanelForwardService) DeleteTunnel(id uint) error
- func (s *PanelForwardService) DiagnoseForwardTargets(ctx context.Context, probes DiagnosisProbes, forwardID uint, publicOnly bool) (*DiagnosisReport, error)
- func (s *PanelForwardService) DiagnoseLocalOperator(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
- func (s *PanelForwardService) DiagnoseNodeXOperator(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
- func (s *PanelForwardService) DiagnoseRuntime(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
- func (s *PanelForwardService) DiagnoseTunnel(id uint) (*TunnelDiagnosisReport, error)
- func (s *PanelForwardService) DiagnoseTunnelContext(ctx context.Context, probes DiagnosisProbes, id uint) (*TunnelDiagnosisReport, error)
- func (s *PanelForwardService) GetForwardWithTunnel(id uint) (*model.Forward, error)
- func (s *PanelForwardService) GetLocalOperatorStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
- func (s *PanelForwardService) GetNodeXOperatorStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
- func (s *PanelForwardService) GetRuntimeStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
- func (s *PanelForwardService) ListAdminTunnels() ([]PanelAdminTunnelItem, error)
- func (s *PanelForwardService) ListForwards(userID uint, isAdmin bool) ([]PanelForwardListItem, error)
- func (s *PanelForwardService) ListTunnels(userID uint, isAdmin bool) ([]PanelTunnelListItem, error)
- func (s *PanelForwardService) ListUserTunnels(query PanelUserTunnelQueryInput) ([]PanelUserTunnelDetailItem, error)
- func (s *PanelForwardService) RecordForwardTraffic(records []PanelForwardTrafficRecord) error
- func (s *PanelForwardService) ResetUserTunnelTraffic(id uint) error
- func (s *PanelForwardService) RuntimeService() *PanelForwardRuntimeService
- func (s *PanelForwardService) UpdateOrder(userID uint, isAdmin bool, updates []PanelForwardOrderUpdate) error
- func (s *PanelForwardService) UploadFluxForwardFlow(data PanelForwardFlowData) error
- type PanelForwardTrafficRecord
- type PanelForwardTrafficSnapshot
- type PanelForwardUpdateInput
- type PanelRuntimeJobFilter
- type PanelTunnelInput
- type PanelTunnelListItem
- type PanelTunnelUpdateInput
- type PanelUserTunnelDetailItem
- type PanelUserTunnelInput
- type PanelUserTunnelQueryInput
- type PanelUserTunnelUpdateInput
- type PaymentGatewayService
- func (s *PaymentGatewayService) CalculateFee(gateway *model.PaymentGateway, amount float64) float64
- func (s *PaymentGatewayService) CheckOrderPayable(orderID, userID uint, amount float64) error
- func (s *PaymentGatewayService) Create(gateway *model.PaymentGateway) error
- func (s *PaymentGatewayService) CreateRecord(record *model.PaymentRecord) error
- func (s *PaymentGatewayService) Delete(id uint) error
- func (s *PaymentGatewayService) FinishPaidOrder(record model.PaymentRecord)
- func (s *PaymentGatewayService) GenerateTradeNo() string
- func (s *PaymentGatewayService) GetByID(id uint) (*model.PaymentGateway, error)
- func (s *PaymentGatewayService) GetByType(gatewayType string) (*model.PaymentGateway, error)
- func (s *PaymentGatewayService) GetChannels() ([]*model.PaymentChannel, error)
- func (s *PaymentGatewayService) GetEnabled() ([]*model.PaymentGateway, error)
- func (s *PaymentGatewayService) GetRecordByTradeNo(tradeNo string) (*model.PaymentRecord, error)
- func (s *PaymentGatewayService) GetStats(start, end time.Time) (*PaymentStats, error)
- func (s *PaymentGatewayService) GetUserRecords(userID uint, page, pageSize int) ([]*model.PaymentRecord, int64, error)
- func (s *PaymentGatewayService) List() ([]*model.PaymentGateway, error)
- func (s *PaymentGatewayService) ListRecords(page, pageSize int, status *int, gatewayType string) ([]*model.PaymentRecord, int64, error)
- func (s *PaymentGatewayService) MarkOrderPaid(tradeNo string, gatewayTradeNo string, notifyData string) error
- func (s *PaymentGatewayService) MarkOrderPaidIfCovered(tradeNo string, gatewayTradeNo string, notifyData string, ...) error
- func (s *PaymentGatewayService) MarkOrderPaidWithAmount(tradeNo string, gatewayTradeNo string, notifyData string, paidAmount *float64) error
- func (s *PaymentGatewayService) ParseConfig(gateway *model.PaymentGateway) (any, error)
- func (s *PaymentGatewayService) Toggle(id uint, enabled bool) error
- func (s *PaymentGatewayService) Update(gateway *model.PaymentGateway) error
- func (s *PaymentGatewayService) ValidateAmount(gateway *model.PaymentGateway, amount float64) error
- func (s *PaymentGatewayService) ValidateGatewayUsable(gateway *model.PaymentGateway) error
- type PaymentStats
- type PlanService
- func (s *PlanService) AssignToUser(planID, userID uint, expireAt *int64, requestID string) error
- func (s *PlanService) Create(p *model.Plan) error
- func (s *PlanService) Delete(id uint) error
- func (s *PlanService) Get(id uint) (*model.Plan, error)
- func (s *PlanService) List() ([]*model.Plan, error)
- func (s *PlanService) Update(p *model.Plan) error
- type PluginCompatibilityRoutes
- type PluginConfigurationSemanticValidator
- type PluginConfigurationTxHook
- type PluginControlRouteResolution
- type PluginDependencyExecutionPlan
- type PluginDependencyExecutionStep
- type PluginDependencyResolution
- type PluginDependencyResolver
- type PluginEntrypoint
- type PluginInstallationStatus
- type PluginManifest
- func DecodePluginReleaseManifest(release model.PluginRelease) (*PluginManifest, error)
- func VerifyPluginRelease(manifestJSON, signature string, publicKey ed25519.PublicKey) (*PluginManifest, error)
- func VerifyStoredPluginRelease(db *gorm.DB, release model.PluginRelease, fallback ed25519.PublicKey) (*PluginManifest, error)
- type PluginMigrations
- type PluginWebUI
- type PluginWebUIBundle
- type PluginWebUIMenu
- type PluginWebUIRoute
- type ProxyNodeCredentials
- type RawNodeConfigValidation
- type RegistrationPolicy
- type RetireCounts
- type RouteCatalogEntry
- type RouteHostObservation
- type RouteModeActor
- type RouteModeAdmin
- func (a *RouteModeAdmin) List(ctx context.Context, packageID string, ...) ([]PackageRouteModes, error)
- func (a *RouteModeAdmin) Revisions(ctx context.Context, packageID string, limit int) ([]model.RouteModeRevision, error)
- func (a *RouteModeAdmin) Rollback(ctx context.Context, packageID, reason string, actor RouteModeActor) (RouteModeResult, error)
- func (a *RouteModeAdmin) Set(ctx context.Context, request RouteModeChangeRequest, actor RouteModeActor) (RouteModeResult, error)
- type RouteModeChange
- type RouteModeChangeRequest
- type RouteModeEntry
- type RouteModeResult
- type RouteModeSkip
- type SecretDocumentOutcome
- type ServerService
- func (s *ServerService) BatchRecordTrafficLog(serverType model.ServerType, serverID uint, traffics map[uint][2]int64, ...) error
- func (s *ServerService) BuildNodeConfig(serverType model.ServerType, serverID uint) (map[string]any, error)
- func (s *ServerService) GetAllUsersOnlineCount() (map[string]int, error)
- func (s *ServerService) GetRoutesByIDs(ids []uint) ([]model.ServerRoute, error)
- func (s *ServerService) GetServerByTypeAndID(serverType model.ServerType, serverID uint) (any, error)
- func (s *ServerService) GetServerUsers(serverType model.ServerType, serverID uint) ([]model.User, error)
- func (s *ServerService) GetUserOnlineCount(userID uint) (int64, error)
- func (s *ServerService) RecordAgentTrafficReport(nodeKind string, nodeID uint, batchID string, traffics map[uint][2]int64, ...) (bool, error)
- func (s *ServerService) RecordNodeTrafficReport(serverType model.ServerType, nodeID uint, traffics map[uint][2]int64, ...) error
- func (s *ServerService) RecordServerStat(serverType model.ServerType, serverID uint, upload, download int64, ...) error
- func (s *ServerService) RecordTrafficLog(serverType model.ServerType, serverID uint, userID uint, ...) error
- func (s *ServerService) UpdateOnlineStatus(serverType model.ServerType, serverID uint, userIPs map[uint][]string) error
- type SettingsAudit
- type SettingsAuditActor
- type SettingsNamespace
- type SettingsStorage
- type SpeedLimitInput
- type SpeedLimitService
- type SpeedLimitUpdateInput
- type StatsService
- func (s *StatsService) GetDashboardStats(forceRefresh bool) (*DashboardStats, error)
- func (s *StatsService) GetHourlyTraffic(hours int, userID uint) ([]HourlyTraffic, error)
- func (s *StatsService) GetNodeTraffic(nodeID uint, granularity string, since, until time.Time) (*NodeTrafficSeries, error)
- func (s *StatsService) GetTrafficLogMeta(userID uint) (TrafficLogMeta, error)
- func (s *StatsService) GetUserSubscription(userID uint, forceRefresh bool) (*UserSubscription, error)
- func (s *StatsService) GetUserTrafficRanking(hours int, limit int, includeZeroUsers bool) ([]UserTrafficRank, error)
- func (s *StatsService) UserSubscriptionSummary(userID uint, forceRefresh bool, configService *SystemConfigService, ...) (*UserSubscription, error)
- type SubscriberEntitlements
- type SubscriptionService
- func (s *SubscriptionService) AssignGroupToPlan(planID, groupID uint) error
- func (s *SubscriptionService) AssignGroupToUser(userID, groupID uint, expireAt *int64, transferEnable *int64, ...) error
- func (s *SubscriptionService) BuildWireGuardRuntimeUserExtras(protocol *model.NodeProtocol, users []*model.User) (map[uint]map[string]string, error)
- func (s *SubscriptionService) CreateGroup(group *model.SubscriptionGroup) error
- func (s *SubscriptionService) CreateTemplate(template *model.SubscriptionTemplate) error
- func (s *SubscriptionService) DeleteGroup(id uint, requestID string) error
- func (s *SubscriptionService) DeleteTemplate(id uint) error
- func (s *SubscriptionService) GetGroup(id uint) (*model.SubscriptionGroup, error)
- func (s *SubscriptionService) GetGroupStats() ([]GroupStats, error)
- func (s *SubscriptionService) GetGroups() ([]*model.SubscriptionGroup, error)
- func (s *SubscriptionService) GetOrCreateWireGuardPeer(protocolID, userID uint, cidr string) (*model.WireGuardPeer, error)
- func (s *SubscriptionService) GetPlanGroups(planID uint) ([]*model.SubscriptionGroup, error)
- func (s *SubscriptionService) GetTemplate(id uint) (*model.SubscriptionTemplate, error)
- func (s *SubscriptionService) GetTemplatesByGroup(groupID uint) ([]*model.SubscriptionTemplate, error)
- func (s *SubscriptionService) GetUserGroups(userID uint) ([]*model.SubscriptionGroup, error)
- func (s *SubscriptionService) GetUserSubscription(req *model.SubscriptionRequest) (*model.SubscriptionResponse, error)
- func (s *SubscriptionService) ListGroupMembers(groupID uint, params GroupMembersParams) (*GroupMembersResult, error)
- func (s *SubscriptionService) RemoveGroupFromPlan(planID, groupID uint) error
- func (s *SubscriptionService) RemoveGroupFromUser(userID, groupID uint, requestID string) error
- func (s *SubscriptionService) UpdateGroup(group *model.SubscriptionGroup) error
- func (s *SubscriptionService) UpdateTemplateFields(id uint, fields map[string]any) error
- type SubscriptionSettings
- type SystemConfigService
- func (s *SystemConfigService) Delete(key string) error
- func (s *SystemConfigService) Get(key string) (string, error)
- func (s *SystemConfigService) GetAll() ([]model.SystemConfig, error)
- func (s *SystemConfigService) GetAsMap() (map[string]string, error)
- func (s *SystemConfigService) GetByGroup(group string) ([]model.SystemConfig, error)
- func (s *SystemConfigService) GetEntry(key string) (*model.SystemConfig, error)
- func (s *SystemConfigService) GetJSON(key string, v any) error
- func (s *SystemConfigService) Set(key, value, cfgType, group, remark string) error
- func (s *SystemConfigService) SetJSON(key string, v any, group, remark string) error
- type TOTPSetup
- type TargetCatalogItem
- type TelegramBotService
- func (s *TelegramBotService) BindUser(telegramID int64, email string, from *TelegramUser) error
- func (s *TelegramBotService) Broadcast(text string) error
- func (s *TelegramBotService) DeleteWebhook() error
- func (s *TelegramBotService) GetBot() (*model.TelegramBot, error)
- func (s *TelegramBotService) GetTelegramUserService() *TelegramUserService
- func (s *TelegramBotService) HandleUpdate(update *TelegramUpdate) error
- func (s *TelegramBotService) ProbeSend(ctx context.Context, bot *model.TelegramBot, chatID int64, text string) TelegramProbeResult
- func (s *TelegramBotService) SendMessage(chatID int64, text string) error
- func (s *TelegramBotService) SendNotification(telegramID int64, title, content string) error
- func (s *TelegramBotService) SetAPIBase(base string)
- func (s *TelegramBotService) SetWebhook(webhookURL string) error
- func (s *TelegramBotService) UpdateBot(bot *model.TelegramBot) error
- func (s *TelegramBotService) ValidWebhookSecret(header string) bool
- type TelegramCallback
- type TelegramChat
- type TelegramMessage
- type TelegramProbeClass
- type TelegramProbeResult
- type TelegramUpdate
- type TelegramUser
- type TelegramUserService
- type Topology
- type TopologyDeploymentDiagnosticCheck
- type TopologyDeploymentDiagnosticIssue
- type TopologyDeploymentEvent
- type TopologyDeploymentExecutor
- func (e *TopologyDeploymentExecutor) Run(ctx context.Context, interval time.Duration, reportError func(error))
- func (e *TopologyDeploymentExecutor) RunOnce(ctx context.Context) (int, error)
- func (e *TopologyDeploymentExecutor) Start(ctx context.Context, interval time.Duration, reportError func(error))
- type TopologyDeploymentOperation
- type TopologyDeploymentPlanInput
- type TopologyDeploymentPreview
- type TopologyDeploymentPreviewInput
- type TopologyDeploymentPreviewStep
- type TopologyDeploymentStatus
- type TopologyDeploymentStatusView
- type TopologyDeploymentStepView
- type TopologyDeploymentView
- type TopologyEdge
- type TopologyNode
- type TopologyObservedStateUpdate
- type TopologyObservedStateView
- type TopologyRevisionInput
- type TopologyValidationIssue
- type TrafficLogMeta
- type TunnelDiagnosisReport
- type UserListItem
- type UserListParams
- type UserListPlan
- type UserListResult
- type UserService
- func (s *UserService) Ban(id uint) error
- func (s *UserService) BatchUpdateTraffic(traffics map[uint][2]int64) error
- func (s *UserService) Create(user *model.User) error
- func (s *UserService) Delete(id uint) error
- func (s *UserService) GetActiveUsers() ([]model.User, error)
- func (s *UserService) GetActiveUsersByGroupID(groupID uint) ([]model.User, error)
- func (s *UserService) GetActiveUsersForNode(groupID *uint) ([]*model.User, error)
- func (s *UserService) GetByEmail(email string) (*model.User, error)
- func (s *UserService) GetByID(id uint) (*model.User, error)
- func (s *UserService) GetByToken(token string) (*model.User, error)
- func (s *UserService) GetByUUID(uuid string) (*model.User, error)
- func (s *UserService) GetList(params UserListParams) (*UserListResult, error)
- func (s *UserService) GetStats() (map[string]any, error)
- func (s *UserService) ResetToken(id uint, requestID string) (string, error)
- func (s *UserService) ResetTraffic(id uint, requestID string) error
- func (s *UserService) Unban(id uint) error
- func (s *UserService) Update(id uint, updates map[string]any) error
- func (s *UserService) UpdateTraffic(userID uint, upload, download int64) error
- func (s *UserService) VerifyStepUp(userID uint, password, code, method string) (bool, error)
- type UserSubscription
- type UserTrafficRank
- type WebUIExtension
- type WebUIExtensionBundle
- type WireGuardPeerRotationResult
Constants ¶
const ( AgentDiagnosticActionServiceStatus = "service_status" AgentDiagnosticActionServiceRestart = "service_restart" AgentDiagnosticActionLogTail = "log_tail" // AgentDiagnosticLogTailMaxLines 限制 log_tail 一次最多返回的行数,避免超大输出。 AgentDiagnosticLogTailMaxLines = 1000 )
const ( // ForwardCheckListen: the hop's own listener holds its port. ForwardCheckListen = "forward.listen" // ForwardCheckPortConflict: no foreign process or nftables rule claims // the hop's listen port. ForwardCheckPortConflict = "forward.port_conflict" // ForwardCheckConnect: a TCP connect to each of the hop's upstreams. ForwardCheckConnect = "forward.connect" // ForwardCheckUDPProbe: a short datagram to each of the hop's upstreams, // waiting for any reply; no reply is inconclusive, not a failure. ForwardCheckUDPProbe = "forward.udp_probe" // ForwardCheckDefaultTimeoutMS is a check's timeout when it names none. ForwardCheckDefaultTimeoutMS = 3000 // ForwardCheckMinTimeoutMS and ForwardCheckMaxTimeoutMS bound it. ForwardCheckMinTimeoutMS = 100 ForwardCheckMaxTimeoutMS = 10000 // ForwardTargetPolicyPublicOnly and ForwardTargetPolicyAllowPrivate are // the target_policy parameter: the most a check may dial among a last // hop's targets. The Agent applies the stricter of it and the hop's own // policy. ForwardTargetPolicyPublicOnly = "public_only" ForwardTargetPolicyAllowPrivate = "allow_private" )
The forward checks of the agent.diagnostic operation (forward-sdk.md section 7.6, F3c): node-vantage probes of one hop of one route, which only the kernel's route diagnosis (kernelforward.DiagnoseRoute) sends. The Agent resolves the hop's listener and upstreams from the NodeForwardState it has applied and probes only those, so a check names a hop, never an address to dial; the optional upstream narrows the check to one of the hop's upstreams. sdk/api/agent/v1/PROTOCOL.md, "Forward diagnostic checks", is the Agent's reference.
const ( ForwardNodeInventoryScopeAny = "" ForwardNodeInventoryScopeNodeX = "nodex" ForwardNodeInventoryScopeAnsible = "ansible" ForwardNodeInventoryTagAnsibleMachine = "ansible-machine" )
const ( InviteCodeFilterAll = "" InviteCodeFilterUnused = "unused" InviteCodeFilterUsed = "used" InviteCodeFilterExpired = "expired" )
Invite code list filters (the status query parameter).
const ( PluginWebUIMenuParentServices = "services" PluginWebUIMenuParentOperations = "operations" PluginWebUIMenuParentSystem = "system" PluginWebUIMenuParentExtensions = "extensions" )
WebUI menu parents are a stable shell contract. Unknown, but otherwise valid, package metadata is kept visible in the explicit extensions bucket instead of creating an unregistered top-level navigation section.
const ( NodeLogLevelDebug = "debug" NodeLogLevelInfo = "info" NodeLogLevelWarning = "warning" NodeLogLevelError = "error" )
const ( // NodeSecretReasonPlaceholder: the field holds the administrators' mask // (********), so the node would receive the mask as its key. NodeSecretReasonPlaceholder = "placeholder" // NodeSecretReasonTombstone: the field holds a tombstone of the // credential split. NodeSecretReasonTombstone = "tombstone" // NodeSecretReasonWireGuardKey: an enabled WireGuard entry's // server_private_key is missing, or a server_private_key is not a // 32-byte standard Base64 X25519 key. NodeSecretReasonWireGuardKey = "wireguard_key" // NodeSecretReasonWireGuardKeyPair: a WireGuard entry's server public // key is not the public key of its server_private_key. NodeSecretReasonWireGuardKeyPair = "wireguard_key_pair" // #nosec G101 -- this names a validation reason, not a credential. // NodeSecretReasonRealityKey: a Reality private_key is not a 32-byte // Base64 key. NodeSecretReasonRealityKey = "reality_key" // NodeSecretReasonSS2022Key: a Shadowsocks 2022 server_key does not // decode to the cipher's key length. NodeSecretReasonSS2022Key = "ss2022_key" // #nosec G101 -- this names a validation reason, not a credential. )
Why a secret fails validation.
const ( CacheKeyNodeList = "nodes:list" CacheKeyNode = "node:" // + nodeID CacheKeyNodeProtocols = "node:protocols:" // + nodeID )
缓存键
const ( // NodeTrafficHour: hourly buckets from the raw traffic log // (v2_server_log), aligned to UTC hours. NodeTrafficHour = "hour" // NodeTrafficDay: daily buckets from the daily server statistics // (v2_stat_server, record_type d), aligned to the local midnight the // statistics were recorded at. NodeTrafficDay = "day" // MaxNodeTrafficHours bounds an hourly series: the same 30 days the // admin hourly traffic page (GetHourlyTraffic) clamps to. MaxNodeTrafficHours = maxHourlyWindow // MaxNodeTrafficDays bounds a daily series. MaxNodeTrafficDays = 366 )
Granularities of a node's traffic series.
const ( // CapabilityNodeOpsForward: ApplyForward, ApplyTunnel, // SyncForwardBackend, ApplyLegacyRule. CapabilityNodeOpsForward = "kernel.nodeops.forward.v1" // CapabilityNodeOpsNodeConfig: SyncNode, RetireNode, RetireProtocol, // PutSecretDocument and ValidateNodeConfig. CapabilityNodeOpsNodeConfig = "kernel.nodeops.nodeconfig.v1" // CapabilityNodeOpsDiagnose: CheckEndpoints, CollectNodeStats, // DiagnoseForward, DiagnoseTunnel, RunAgentDiagnostic. CapabilityNodeOpsDiagnose = "kernel.nodeops.diagnose.v1" // CapabilityNodeOpsAgents: AgentControlOperation and the agent session // reads. CapabilityNodeOpsAgents = "kernel.nodeops.agents.v1" // CapabilityNodeOpsCredentials: IssueCredential, RevokeCredential, // IssueRegistrationKey, RevokeRegistrationKey, IssueCleanAgent. CapabilityNodeOpsCredentials = "kernel.nodeops.credentials.v1" // #nosec G101 -- a capability name, not a credential. )
The KernelNodeOps operation families (node-ops-service.md section 3.2). Each lets an official package submit one family's node operations; any one of them lets it read, watch and cancel the operations it owns.
const ( // OrderPaymentCompleted: the order was marked paid and completed. OrderPaymentCompleted = "completed" // OrderPaymentPaid: the order was marked paid, but granting its plan // failed; it stays paid for an administrator to complete. OrderPaymentPaid = "paid" // OrderPaymentRefused: the record does not pay its order, which is left // unchanged; the payment stays recorded. OrderPaymentRefused = "refused" )
Outcomes of CompleteOrderPaymentTx: what a paid payment record did to the order it names (docs/architecture/order-service.md).
const ( // OrderPaymentReconcileGrace is how long a paid record is left to the // callback that paid it before the reconciler completes its order. The // payment module commits the record, then asks KernelOrder; the grace // keeps the reconciler out of that live second step. OrderPaymentReconcileGrace = 2 * time.Minute // OrderPaymentReconcileBatch is how many records one query reads. OrderPaymentReconcileBatch = 100 // OrderPaymentReconcileMaxBatches bounds the batches of one run; a // larger backlog continues on the next run. OrderPaymentReconcileMaxBatches = 10 )
const ( // PackageReportRefusedInvalid: plugin_id, kind or version is malformed. PackageReportRefusedInvalid = "invalid" // PackageReportRefusedOversize: payload_json exceeds 256 KiB. PackageReportRefusedOversize = "oversize" // PackageReportRefusedFuture: observed_at is more than a minute ahead. PackageReportRefusedFuture = "future" // PackageReportRefusedUnknownKind: the kernel knows no such kind. PackageReportRefusedUnknownKind = "unknown_kind" // PackageReportRefusedNotAssigned: the plugin is not enabled on the node. PackageReportRefusedNotAssigned = "not_assigned" // PackageReportRefusedVersionMismatch: the node is assigned another // version of the plugin. PackageReportRefusedVersionMismatch = "version_mismatch" // PackageReportRefusedUnsigned: the release is not a signed official // (AnixOps) release, or its signature no longer verifies. PackageReportRefusedUnsigned = "unsigned" // PackageReportRefusedMissingCapability: the release is not an Agent // release declaring the kind's capability. PackageReportRefusedMissingCapability = "missing_capability" // PackageReportRefusedBadPayload: the kind's sanitizer refused the // payload. PackageReportRefusedBadPayload = "bad_payload" // PackageReportRefusedUnnegotiated: a forward report (plugin_id // "forward", kind "forward.report") on a session that did not negotiate // forward.v1. PackageReportRefusedUnnegotiated = "unnegotiated" )
Why a package report was refused: the reason label of anixops_agent_package_reports_refused_total.
const ( // PackageRouteDefaultRehearsed: the routes of // config/package-route-defaults.json run natively when no mode is stored // for them and the installed release is at least the rehearsed one. PackageRouteDefaultRehearsed = "rehearsed" // PackageRouteDefaultLegacy: the kill switch; no route defaults to // native. PackageRouteDefaultLegacy = "legacy" )
Package route default policies (package_routes.default_mode).
const ( // RouteModeSourceStored: the installation's configuration stores the // mode (anix-control routes set/rollback, the identity cutover). RouteModeSourceStored = "stored" // RouteModeSourceDefault: no stored mode; the route is in the rehearsed // default set and runs natively. RouteModeSourceDefault = "default" // RouteModeSourceKillSwitch: no stored mode; the route is in the // default set, but package_routes.default_mode is legacy. RouteModeSourceKillSwitch = "kill-switch" // RouteModeSourcePackageTooOld: no stored mode; the route is in the // default set, but the installed release is older than the rehearsed // one. RouteModeSourcePackageTooOld = "package-too-old" // RouteModeSourceIdentityAuthority: no stored mode; an identity group A // route, native because identity is authoritative. RouteModeSourceIdentityAuthority = "identity-authority" // RouteModeSourceUnset: no stored mode and no default: legacy. RouteModeSourceUnset = "unset" )
Where a route's mode comes from (RouteModeEntry.Source).
const ( RouteCatalogBridged = "bridged" RouteCatalogKernelOwned = "kernel-owned" RouteCatalogNativeFlagged = "native-flagged" RouteCatalogNative = "native" )
Package extraction modes (config/package-extraction.json).
const ( RouteModeLockKernelOwned = "kernel_owned" RouteModeLockIdentityGroupA = "identity_group_a" RouteModeLockWebSocket = "websocket" RouteModeLockNotDeclared = "not_declared" RouteModeLockNativeOnly = "native_only" )
Reasons a route is locked to its current mode in the administration.
const ( PluginPermissionModeLegacy = "legacy" PluginPermissionModeAuthoritative = "authoritative" PluginPermissionModeMixed = "mixed" )
const ( // CapabilityObservedState lets an Agent-target package report observed // runtime state. CapabilityObservedState = "kernel.observed-state" // CapabilityStorage leases a per-package database role and schema. CapabilityStorage = "kernel.storage.v1" // CapabilityIdentity lets the official identity package call the // KernelIdentity contract (subscribers, account projection, revocation). CapabilityIdentity = "kernel.identity.v1" // CapabilityOrderComplete lets an official package call // KernelOrder.CompleteOrderPayment (order-service.md): a paid payment // record marks its order paid and completes it. CapabilityOrderComplete = "kernel.order.complete.v1" // The KernelSubscriber method families (subscriber-service.md): each // lets an official package call one part of the subscriber contract. CapabilitySubscriberEntitlements = "kernel.subscriber.entitlements.v1" CapabilitySubscriberTraffic = "kernel.subscriber.traffic.v1" CapabilitySubscriberCredentials = "kernel.subscriber.credentials.v1" CapabilitySubscriberBalance = "kernel.subscriber.balance.v1" CapabilitySubscriberDirectory = "kernel.subscriber.directory.v1" // CapabilitySubscriberGroups edits one subscription group membership // (v2_user_subscription_group) at a time. CapabilitySubscriberGroups = "kernel.subscriber.groups.v1" // CapabilitySubscriberSummary reads one subscriber's cached // subscription summary (kernel-caches.md). CapabilitySubscriberSummary = "kernel.subscriber.summary.v1" // CapabilityForward lets an official package call ForwardControl // (forward-sdk.md section 8, F3a): route writes and reads, the dry-run // planner, statistics and health of the kernel's forwarding state. CapabilityForward = "kernel.forward.v1" // CapabilityTelemetryDashboard lets an official package call // KernelTelemetry.GetDashboard (kernel-caches.md): the administrator // dashboard's snapshot from the kernel's cache, with the online users // as a count. CapabilityTelemetryDashboard = "kernel.telemetry.dashboard.v1" )
Capabilities in the kernel. namespace grant kernel authority to a signed package, so only the forms below are accepted. Other namespaces are package vocabulary and only need a well-formed, unique name.
const ( // SettingsNamespaceMail is the SMTP delivery configuration // (notification.email.*). SettingsNamespaceMail = "mail" // SettingsNamespaceInvite is the affiliate's frontend settings // (invite.*). SettingsNamespaceInvite = "invite" // SettingsNamespaceNodeX is the NodeX control plane address, shared // token and timeout (forward.runtime.nodex.*). SettingsNamespaceNodeX = "nodex" // SettingsNamespaceForwardRuntime is the forward runtime backend and // its local Ansible settings. SettingsNamespaceForwardRuntime = "forward-runtime" // SettingsNamespaceBackup is the backup configuration row of // v2_backup_config, one key per field (backup.<field>). SettingsNamespaceBackup = "backup" )
Settings namespaces (docs/architecture/settings-service.md). Every setting key belongs to at most one namespace, which the KernelSettings contract authorizes per capability; a key in no namespace is reachable through no contract call.
const ( SettingsAccessRead = "read" SettingsAccessWrite = "write" SettingsAccessSecrets = "secrets" )
Settings capability accesses: kernel.settings.<namespace>.<access>.v1.
const ( CacheKeyDashboardStats = "stats:dashboard" CacheKeyUserStats = "stats:users" CacheKeyOrderStats = "stats:orders" CacheKeyNodeStats = "stats:nodes" CacheKeyUserSubscription = "user:subscription:" // + userID )
缓存键
const ( StatsCacheTTL = 60 * time.Second // 统计数据缓存 60 秒 SubscriptionCacheTTL = 30 * time.Second // 用户订阅缓存 30 秒 NodeCacheTTL = 10 * time.Second // 节点缓存 10 秒 )
缓存过期时间
const ( SubscriptionResetRateLimitedMessage = "too many subscription reset attempts, please try again later" SubscriptionResetFailedMessage = "重置订阅失败" )
The answers of a subscription reset that does not reset; identity-platform answers the same messages.
const ( TelegramReasonTimeout = "timeout" TelegramReasonDNS = "dns" TelegramReasonTLS = "tls" TelegramReasonConnect = "connect" TelegramReasonCanceled = "canceled" TelegramReasonOther = "other" )
The reasons of a network_error, from a fixed list.
const ( AdminUserResetTraffic = "reset_traffic" AdminUserResetSubscribe = "reset_subscribe" )
Administrator resets of one user, for AdminUserResetRequestID.
const AgentPluginInstallAPIVersion = "anixops.io/plugin-install/v1alpha1"
const BackupSettingsPrefix = "backup."
BackupSettingsPrefix starts every key of the backup namespace.
const ( // DefaultDiagnosisConcurrency bounds the probes one diagnosis runs at // once. DefaultDiagnosisConcurrency = 8 )
const DefaultForwardRuntimeJobScrubBatch = 200
DefaultForwardRuntimeJobScrubBatch bounds the rows one scrub transaction rewrites.
const DefaultInviteCodeLimit = 5
DefaultInviteCodeLimit is how many unused invite codes a user may hold when the invite configuration sets no code_count, as v2board's invite_gen_limit defaults to 5.
const IdentityPlatformPackageID = "identity-platform"
IdentityPlatformPackageID is the package whose group A the identity module serves once it is authoritative.
const InviteCodeLimitMessage = "The maximum number of creations has been reached"
InviteCodeLimitMessage is the answer at the limit, v2board's.
const KernelOperationEnvelopeVersion = "anixops.operation/v1"
const LegacyForwardCleanupPlaybook = "config/deploy/ansible/playbooks/forward_legacy_cleanup.yml"
LegacyForwardCleanupPlaybook is the Ansible cleanup playbook, relative to the repository root like the other forward playbooks.
const MaxAdminInviteCodeBatch = 50
MaxAdminInviteCodeBatch is how many codes one administrator request may generate.
const MaxAdminInviteCodeExpireDays = 3650
MaxAdminInviteCodeExpireDays bounds an administrator's expiry override.
const MaxOrderPaymentTradeNo = 120
MaxOrderPaymentTradeNo keeps OrderPaymentRequestID within the request ledger's 128 bytes. Generated trade numbers are 26 bytes and the column holds 64.
const MaxPluginArtifactBytes = 64 << 20
const NodeLogSourceMaintenance = "maintenance"
NodeLogSourceMaintenance is the source of the node log rows that record an Agent's maintenance events (maintenance.v1).
const NodeSecretPlaceholder = SensitiveSystemConfigPlaceholder
NodeSecretPlaceholder stands for a node secret in the administrator's answers: a secret setting of a node protocol or of a node's raw configuration, a forward node's API token, a registration key. Sending it back in a write keeps the stored secret, as for system configuration and payment gateway secrets. Nodes and agents read their configuration through their own authenticated paths (UniProxy, the gRPC node service, agent control), which build it from the stored rows and never see the placeholder.
const NodeSortTiebreaker = "id DESC"
NodeSortTiebreaker orders nodes that share a sorted value, so pages neither repeat nor skip a node.
const OrderPaymentMethod = "complete_order_payment"
OrderPaymentMethod is the request ledger method of a payment's order completion.
const OrderSortTiebreaker = "id DESC"
OrderSortTiebreaker orders orders that share a sorted value, so pages neither repeat nor skip an order.
const PackageRouteModesConfigKey = "routes"
PackageRouteModesConfigKey is the kernel-reserved key of a Control package configuration document. It maps v2 route ids to legacy, shadow or native; the kernel validates it and removes it before the package's own config_schema is applied.
const PluginAPIGrantResourceType = "plugin_api"
const PluginArtifactCopyPrefix = ".anix-package-"
PluginArtifactCopyPrefix names the per-process package copies created under the Control plugin artifact directory.
const RouteModeCLIActor = "system/cli"
RouteModeCLIActor is the actor the command line records in the audit log and the revision history.
const SensitiveSystemConfigPlaceholder = "********"
const SubscriberReissueMethod = "reset_credentials"
SubscriberReissueMethod is the subscriber request ledger's method for a new subscription token or proxy uuid (KernelSubscriber.ResetCredentials and the administrator's subscription reset).
const SystemConfigKeySubscribeDomains = "app.subscribe_domains"
const UserSortTiebreaker = "id DESC"
UserSortTiebreaker orders users that share a sorted value, so pages neither repeat nor skip a user.
const UserSubscriptionReset = "user_reset_subscribe"
UserSubscriptionReset is a user's reset of their own subscription token, for UserSubscriptionResetRequestID.
Variables ¶
var ( ErrAgentPluginAssignmentDenied = errors.New("node is not assigned the requested plugin release") ErrAgentPluginAssignmentConflict = errors.New("node plugin assignments have conflicting desired state") ErrAgentPluginReleaseIntegrity = errors.New("agent plugin release integrity check failed") ErrAgentPluginReconcileNotReady = errors.New("agent plugin assignment is not ready to reconcile") ErrAgentPluginAddressMismatch = errors.New("agent plugin download address does not match verified content") )
var ( ErrForwardCleanAgentRevoked = errors.New("forward clean agent revoked") // ErrForwardCleanAgentNodeMismatch refuses an agent's registration // under a node other than the one its token is bound to. ErrForwardCleanAgentNodeMismatch = errors.New("forward clean agent is bound to another node") // ErrForwardCleanAgentNodeRequired refuses to issue a token without the // forward node it is for. ErrForwardCleanAgentNodeRequired = errors.New("nodeId is required: a clean agent token is issued for one forward node") // ErrForwardCleanAgentNodeNotFound refuses to issue a token for a forward // node that does not exist. ErrForwardCleanAgentNodeNotFound = errors.New("forward node not found") )
var ( ErrPanelForwardNotFound = errors.New("转发不存在") ErrPanelTunnelNotFound = errors.New("隧道不存在") ErrPanelForwardNodeNotFound = errors.New("节点不存在") )
Errors of the diagnoses' lookups. Their texts are what the legacy routes answer.
var ( // ErrInviteCodeNotFound is a code id that does not exist. ErrInviteCodeNotFound = errors.New("invite code not found") // ErrInviteCodeUsed is a code that registration already consumed; it // stays as the record of who used it. ErrInviteCodeUsed = errors.New("invite code already used") // ErrInviteCodeFilter is a status filter the list does not know. ErrInviteCodeFilter = errors.New("invalid invite code status filter") )
var ( // ErrWithdrawAmountNotWhole: the commission balance is a whole number // of cents, so a withdrawal is too. ErrWithdrawAmountNotWhole = errors.New("amount must be a whole number") // ErrWithdrawalProcessed: the withdrawal is no longer pending, because // another decision processed it first. ErrWithdrawalProcessed = errors.New("withdrawal already processed") )
Withdrawal errors. Their messages are the v2 answers.
var ( ErrInvalidKernelOperationID = errors.New("operation_id must be a UUID") ErrKernelOperationNotPending = errors.New("operation is not cancellable") ErrPluginTrustRootRequired = errors.New("official plugin trust root is required") ErrExtensionCatalogIntegrity = errors.New("extension catalog integrity check failed") ErrPluginConfigurationConflict = errors.New("plugin configuration revision conflict") ErrPluginDependencyUnsatisfied = errors.New("plugin dependency is not enabled") ErrPluginConflict = errors.New("plugin conflict is enabled") ErrPluginArtifactRequired = errors.New("verified plugin artifact is required") ErrPluginArtifactImmutable = errors.New("plugin artifact is immutable") ErrPluginRouteNotFound = errors.New("plugin control route is not registered") ErrPluginRouteForbidden = errors.New("plugin control route permission denied") ErrPackageMigrationImmutable = errors.New("package migration run is immutable") ErrValidationPrecondition = errors.New("package validation precondition failed") ErrCohortTransition = errors.New("package cohort transition is invalid") ErrRollbackPrecondition = errors.New("package rollback precondition failed") )
var ( ErrOrderPaymentRecordNotFound = errors.New("payment record not found") ErrOrderPaymentNotPaid = errors.New("payment record is not paid") ErrOrderPaymentOtherOrder = errors.New("payment record does not name the order") ErrOrderPaymentRequestTaken = errors.New("the payment's request id is taken by another write") )
Errors of CompleteOrderPaymentTx. They record nothing: a later call may apply.
var ( ErrOrderNotFound = errors.New("订单不存在") ErrOrderPlanNotFound = errors.New("关联套餐不存在") )
var ( // ErrRouteModeRejected: the change breaks a route-mode rule; the // message names the route and the rule. ErrRouteModeRejected = errors.New("route mode change rejected") // ErrRouteModeConfirmationRequired: a switch to native needs an // explicit confirmation and a reason. ErrRouteModeConfirmationRequired = errors.New("switching to native needs confirmation and a reason") // ErrRouteModePackageNotInstalled: the package has no Control // installation. ErrRouteModePackageNotInstalled = errors.New("the package has no Control installation") )
Errors of the route-mode administration.
var ( ErrPaymentOrderNotFound = errors.New("订单不存在") ErrPaymentOrderNotPending = errors.New("订单已支付或已取消") ErrPaymentAmountMismatch = errors.New("支付金额与订单金额不符") )
Errors of CheckOrderPayable, in the messages the payment routes answer.
var ( ErrPlanNotFound = errors.New("套餐不存在") ErrPlanUserNotFound = errors.New("用户不存在") )
var ( ErrPluginDependencyGraphEmpty = errors.New("plugin dependency graph is empty") ErrPluginDependencyGraphRootRequired = errors.New("plugin dependency graph root is required") ErrPluginDependencyGraphDuplicateManifest = errors.New("duplicate plugin manifest in dependency graph") ErrPluginDependencyGraphDuplicateRoot = errors.New("duplicate plugin dependency graph root") ErrPluginDependencyGraphInvalid = errors.New("invalid plugin dependency graph manifest") ErrPluginDependencyGraphSelf = errors.New("plugin dependency graph contains a self dependency") ErrPluginDependencyGraphDuplicate = errors.New("plugin dependency graph contains a duplicate relationship") ErrPluginDependencyGraphMissing = errors.New("plugin dependency graph dependency is missing") ErrPluginDependencyGraphCycle = errors.New("plugin dependency graph contains a cycle") ErrPluginDependencyGraphConflict = errors.New("plugin dependency graph contains a conflict") )
The graph resolver operates on releases that have already passed signature and manifest admission. These errors describe graph-level failures so the caller can distinguish a malformed graph from a package-manager failure.
var ( ErrStepUpPasswordRequired = errors.New("password required") ErrStepUpInvalidPassword = errors.New("invalid password") ErrStepUpMFARequired = errors.New("mfa code required") ErrStepUpInvalidMFACode = errors.New("invalid mfa code") )
Step-up errors: the re-authentication a user's own subscription reset needs. Their messages are the panel answers.
var ( ErrSubscriptionUserNotFound = errors.New("用户不存在") ErrSubscriptionPlanNotFound = errors.New("套餐不存在") ErrSubscriptionGroupNotFound = errors.New("分组不存在") ErrSubscriptionUserGroupNotFound = errors.New("用户订阅分组不存在") ErrSubscriptionPlanGroupNotFound = errors.New("套餐订阅分组不存在") )
var ( ErrTopologyDeploymentNotPlanned = errors.New("topology deployment is not planned") ErrTopologyDeploymentTerminal = errors.New("topology deployment is already terminal") ErrTopologyDeploymentBusy = errors.New("topology has an active deployment") )
var AgentDiagnosticActions = map[string]AgentDiagnosticActionSpec{ AgentDiagnosticActionServiceStatus: {Params: []string{"service"}, Mutating: false}, AgentDiagnosticActionServiceRestart: {Params: []string{"service"}, Mutating: true}, AgentDiagnosticActionLogTail: {Params: []string{"service", "lines"}, Mutating: false}, }
AgentDiagnosticActions 是终端功能允许下发的全部动作,不接受任意 action 字符串。
var ErrAdminPasswordRequired = errors.New("no administrator exists and no admin password is configured: set ANIX_CONTROL_ADMIN_PASSWORD or ANIX_CONTROL_ADMIN_PASSWORD_FILE before the first start")
ErrAdminPasswordRequired means the first administrator must be created but no password is configured. A password is never generated or printed: set ANIX_CONTROL_ADMIN_PASSWORD or ANIX_CONTROL_ADMIN_PASSWORD_FILE before the first start.
var ErrAgentDiagnosticTaskOfAnotherNode = errors.New("diagnostic task belongs to another node")
ErrAgentDiagnosticTaskOfAnotherNode is CompleteTask's answer to a result for a task that belongs to another node.
var ErrCapabilityNotAuthorized = errors.New("package is not authorized for the kernel capability")
ErrCapabilityNotAuthorized means the calling host may not use a kernel contract method family.
var ErrForwardNodeEndpointUnconfirmed = nodesecrets.ErrEndpointUnconfirmed
ErrForwardNodeEndpointUnconfirmed is nodesecrets.ErrEndpointUnconfirmed as the forward runtime reports it: the kernel did not present the node's token because the node's address is not its pinned endpoint.
var ErrForwardRuleAdminOnly = errors.New("only administrators can create or change legacy forward rules; forward through your tunnels instead")
ErrForwardRuleAdminOnly refuses a user's write of a legacy forward rule.
var ErrIdentityNotAuthorized = errors.New("package is not authorized for kernel.identity.v1")
ErrIdentityNotAuthorized means the calling host may not use KernelIdentity.
var ErrInvalidMemberStatus = errors.New("status must be active or expired")
ErrInvalidMemberStatus is a members status filter that is not "active" or "expired".
var ErrInvalidNodeProtocol = errors.New("invalid node protocol")
var ErrInviteCodeLimit = errors.New("invite code limit reached")
ErrInviteCodeLimit is returned by GenerateUserInviteCode when the user already holds as many unused invite codes as allowed.
var ErrMFAAlreadyEnabled = errors.New("MFA already enabled; disable it first")
ErrMFAAlreadyEnabled refuses a new TOTP secret for an account whose second factor is enabled; the identity module says the same.
var ErrNegativeTraffic = errors.New("traffic values must be non-negative")
var ErrNodeProtocolNotFound = errors.New("协议不存在")
ErrNodeProtocolNotFound indicates at least one requested node protocol ID does not exist.
var ErrNodeTrafficNode = errors.New("node not found")
ErrNodeTrafficNode is a node traffic request for a node that does not exist.
var ErrNodeTrafficWindow = errors.New("invalid node traffic window")
ErrNodeTrafficWindow is a bad granularity or window of a node traffic request; its text says what is wrong.
var ErrPaymentNotCovered = errors.New("payment not applied")
ErrPaymentNotCovered is returned, wrapped with the reason, when a paid callback does not pay what its payment record asks for. Nothing is written: the record stays pending and its order unpaid.
var ErrRawNodeConfigNotObject = errors.New("raw config must be an object")
ErrRawNodeConfigNotObject refuses a raw configuration that is not a JSON object.
var ErrRemoteRuntimeDisabled = errors.New("the remote module runtime is not enabled (module_runtime.enabled)")
ErrRemoteRuntimeDisabled means the remote runtime is not enabled in the kernel configuration.
var ErrUserNotFound = errors.New("用户不存在")
ErrUserNotFound is returned when a mutating user operation targets no row.
var ForwardDiagnosticChecks = map[string]AgentDiagnosticActionSpec{ ForwardCheckListen: {Params: []string{"route_id", "hop_index", "generation", "timeout_ms"}}, ForwardCheckPortConflict: {Params: []string{"route_id", "hop_index", "generation", "timeout_ms"}}, ForwardCheckConnect: {Params: []string{"route_id", "hop_index", "generation", "timeout_ms", "upstream", "target_policy"}}, ForwardCheckUDPProbe: {Params: []string{"route_id", "hop_index", "generation", "timeout_ms", "upstream", "target_policy"}}, }
ForwardDiagnosticChecks lists the forward checks with their parameters. None changes the node.
var IdentityAccountReadRoutes = []string{
"identity.user.profile.get",
"identity.user.dashboard.get",
"identity.admin.users.id.get",
"identity.admin.users.get",
"identity.admin.users.stats.get",
}
IdentityAccountReadRoutes are identity-platform's read routes whose native handlers take the account (email, administrator, staff and ban flags) from identity's own store: the user's profile and dashboard and the administrator's user detail, user list and user statistics (which search and count identity's accounts with Control's subscriber views in one query). Identity's store is current only while identity is authoritative; before, the legacy handlers change accounts and identity learns of it at the next import. These routes therefore leave legacy mode (shadow or native) only while identity is authoritative, and the rollback returns them to legacy with group A. In legacy mode they read Control's projection, which identity keeps current, so they may stay legacy at any time; they are not part of group A and switch on their own.
var IdentityGroupARoutes = []string{
"identity.auth.login",
"identity.auth.register",
"identity.user.mfa.status.get",
"identity.user.mfa.totp.setup.post",
"identity.user.mfa.totp.enable.post",
"identity.user.mfa.disable.post",
"identity.user.mfa.verify.post",
"identity.user.mfa.backup_codes.regenerate.post",
"identity.admin.mfa.config.get",
"identity.admin.mfa.config.put",
"identity.admin.users.post",
"identity.admin.users.id.put",
"identity.admin.users.id.ban.post",
"identity.admin.users.id.unban.post",
"identity.admin.users.id.delete",
"identity.user.subscription.reset.post",
}
IdentityGroupARoutes are identity-platform's routes that move from the kernel's legacy handlers to identity together, with the authority state: login, registration, MFA, the admin MFA configuration, the admin account writes, and the user's own subscription reset, which checks the user's password or second factor before it resets.
var NodeSortColumns = map[string]v2compat.SortColumn{ "id": {Expr: "id", Unique: true}, "name": {Expr: "name"}, "host": {Expr: "host"}, "sort": {Expr: "sort"}, "created_at": {Expr: "created_at"}, "last_check_at": {Expr: "last_check_at", Nullable: true}, "cpu_usage": {Expr: "cpu_usage"}, "online_users": {Expr: "online_users"}, }
NodeSortColumns are the columns GET /api/v2/admin/nodes sorts by (the sort and order query values, v2compat.ParseListSort). The proxy-node package's native list sorts by the same keys (packages/proxy-node/native), so both answer the same order. "sort" is the administrator's own order weight. A node's shown status is derived from its last check and its protocol count from another table, so neither is sortable here; a node that never checked in (NULL last_check_at) sorts last ascending.
var OrderSortColumns = map[string]v2compat.SortColumn{ "id": {Expr: "id", Unique: true}, "trade_no": {Expr: "trade_no", Unique: true}, "status": {Expr: "status"}, "type": {Expr: "type"}, "total_amount": {Expr: "total_amount"}, "created_at": {Expr: "created_at"}, "paid_at": {Expr: "paid_at", Nullable: true}, }
OrderSortColumns are the columns GET /api/v2/admin/orders sorts by (the sort and order query values, v2compat.ParseListSort). The order package's native list sorts by the same keys (packages/order/native), so both answer the same order. The buyer's e-mail and the plan's name come from other tables and are not sortable here; an unpaid order (NULL paid_at) sorts last ascending.
var PackageReportRefusalReasons = []string{ PackageReportRefusedInvalid, PackageReportRefusedOversize, PackageReportRefusedFuture, PackageReportRefusedUnknownKind, PackageReportRefusedNotAssigned, PackageReportRefusedVersionMismatch, PackageReportRefusedUnsigned, PackageReportRefusedMissingCapability, PackageReportRefusedBadPayload, PackageReportRefusedUnnegotiated, }
PackageReportRefusalReasons lists every refusal reason, in metric order.
var SubscriptionResetRateLimit = LoginRateLimitOptions{ Enabled: true, MaxAttempts: 3, Window: time.Hour, Lockout: time.Hour, CleanupAfter: 2*time.Hour + 5*time.Minute, }
SubscriptionResetRateLimit bounds a user's subscription resets: every attempt that checks a credential counts, successful or not, and the third in an hour locks the user's resets for an hour. identity-platform applies the same limit (packages/identity-platform/native).
var UserSortColumns = map[string]v2compat.SortColumn{ "id": {Expr: "id", Unique: true}, "email": {Expr: "email", Unique: true}, "created_at": {Expr: "created_at"}, "expired_at": {Expr: "expired_at", Nullable: true}, "traffic": {Expr: "(u + d)"}, "transfer_enable": {Expr: "transfer_enable"}, }
UserSortColumns are the columns GET /api/v2/admin/users sorts by (the sort and order query values, v2compat.ParseListSort). The identity package's native list sorts by the same keys (packages/identity-platform/native), so both answer the same order. "traffic" is the used traffic, u + d; a user without an expiry (NULL) sorts last ascending.
Functions ¶
func ActiveUsersForNodeQuery ¶ added in v4.1.0
ActiveUsersForNodeQuery restricts a v2_user query to the users a node serves: the active subscribers (subscriber.Active) of the node's plan group, or every active subscriber when groupID is nil. The legacy user pulls (UniProxy user, v2board GetUsers) and the Agent Control user deltas read the same query, so a node gets the same set on either transport.
func AdminUserResetRequestID ¶ added in v4.1.0
AdminUserResetRequestID names an administrator's traffic or subscription reset of a user in the subscriber request ledger, so a retried request is applied once. token identifies the HTTP request: its Idempotency-Key, else its request id. The identity package's native handlers derive the same id (packages/identity-platform/native), so a retry is recognized whichever side serves it; a new request is a new reset, as in v2.
func AdvancePackageCohort ¶
func AdvancePackageCohort(db *gorm.DB, generationID uint, target uint8) (*model.PackageRouteGeneration, error)
AdvancePackageCohort creates the next immutable route generation only for the canonical 1, 5, 25, 100 rollout sequence. Retrying the exact request returns the previously-created successor.
func AllocateNodeOperationRevision ¶ added in v4.2.0
AllocateNodeOperationRevision reserves the next desired revision of nodeID: one above both the stored cursor and floor (the highest revision the caller already knows was sent), and stores it.
func AmountPaysOrder ¶ added in v4.1.0
AmountPaysOrder reports whether amount (yuan) is an order's total (cents) to the cent.
func ApplyTopologyObservedStateTx ¶
func ApplyTopologyObservedStateTx(tx *gorm.DB, update TopologyObservedStateUpdate) (*model.TopologyObservedState, bool, error)
ApplyTopologyObservedStateTx is the transaction form used by gRPC observed callbacks so operation and topology state commit atomically.
func AuditUsername ¶ added in v4.1.0
AuditUsername is the username the audit trail records for userID when the request names none: the user's e-mail, which the kernel's handlers record for a signed-in administrator. A request the package bridge relays to a legacy handler, and a KernelSettings call, carry the actor's id only. An unknown user, or a failed lookup, records none.
func BackupConfigAuditContent ¶ added in v4.1.0
func BackupConfigAuditContent(cfg *model.BackupConfig, preservedSensitiveFields []string) string
BackupConfigAuditContent is the content of a backup configuration audit entry.
func BeginPackageMigration ¶
func BeginPackageMigration(db *gorm.DB, input model.PackageMigrationRun) (*model.PackageMigrationRun, error)
BeginPackageMigration creates one generation-fenced migration run. A retry with the same immutable input returns the original run and its latest checkpoint so an interrupted host call can resume safely.
func BootstrapIdentityPlatformPackage ¶
BootstrapIdentityPlatformPackage imports exactly one signed identity package before HTTP routes are exposed. This is the only package allowed through the unauthenticated cold-start path; every later package admission stays behind the authenticated kernel API.
A bootstrap never changes an installation that exists, with one exception (moveRetiredRootIdentityInstallation): after the official signing root changed, an installation whose release is bound to a retired root moves to the bootstrap release, which has just been verified under the active root.
func BuildLoginRateLimitKey ¶
func BuildNodeProtocolConfig ¶
BuildNodeProtocolConfig 从 Node + NodeProtocol 构建下发给节点的完整协议配置。
这是节点拉配置的**唯一真源**: HTTP UniProxy handler 和 gRPC 两个配置构建函数 都调它, 避免"改了一处忘了另一处"(SS2022 server_key 之前就是只在订阅端修了, gRPC 节点拿不到)。输出字段名与老 UniProxy JSON 保持一致:
node_type, type, host, server_port, server_name, tls, network, cipher, server_key, flow, tls_settings, network_settings, send_through, routes, base_config, 以及 custom_config 覆盖的任意字段
SS2022 (2022-blake3-*) 的 server_key 若 Settings 未显式给出, 按老 XBoard 算法 从节点 created_at 派生 (子节点用父节点 created_at), 与订阅端 DeriveSS2022ServerKey 和节点端 V2bX 三方一致。
The protocol's secrets are read through the node credential split, in the table's phase, and checked first: a protocol whose secrets fail validation is reported (ReportNodeSecretFindings) and still built, since validation is report-only until decision D7 is enforced.
func BuildUniProxyNodeConfig ¶ added in v4.1.0
func BuildUniProxyNodeConfig(db *gorm.DB, nodeID uint, preferredType string) (map[string]any, error)
BuildUniProxyNodeConfig builds the configuration UniProxy answers a proxy node (GET /api/v1/server/UniProxy/config, and the /api/v2 alias) for the node type it asks for, "" for none: the node's raw configuration when it has one, with the base fields filled in; else the enabled protocol of that type (the first enabled protocol for none) through BuildNodeProtocolConfig; else, for none, a minimal VLESS configuration. The answer is the map UniProxy encodes, field for field. The desired configuration of the Agent Control stream carries it too (kernelnodeops, node-ops-service.md section 5.5), so a node gets the same configuration on either transport. gorm.ErrRecordNotFound when the node does not exist.
func BumpSettingsGeneration ¶ added in v4.1.0
BumpSettingsGeneration marks the namespace changed, so every in-memory copy of it reloads, and returns the new generation. Call it after the change committed.
func BumpSettingsGenerationAfter ¶ added in v4.1.0
BumpSettingsGenerationAfter bumps namespace after a write that read its generation before writing, and reports whether the writer may keep the value it wrote as its in-memory copy at the new generation: only when no other write bumped the namespace in between, else the copy must reload.
func CancelKernelOperation ¶
func CanonicalKernelOperationConfig ¶
CanonicalKernelOperationConfig normalizes a JSON config before it becomes part of an idempotency identity and Agent envelope. This makes hash and retry behavior independent of request whitespace or object key ordering.
func CanonicalPluginManifest ¶
func CanonicalPluginManifest(manifest PluginManifest) ([]byte, error)
CanonicalPluginManifest is the exact byte representation that AnixOps signs and verifies. Schema JSON is recursively parsed and re-encoded so whitespace or object-key ordering cannot change a release signature.
func CreateKernelOperation ¶
func CreateKernelOperation(db *gorm.DB, operation model.KernelOperation) (*model.KernelOperation, bool, error)
CreateKernelOperation persists a requested operation before it can be sent to an agent. A repeated idempotency key returns the original operation, including after a control-plane restart.
func CreateTopologyRevision ¶
func CreateTopologyRevision(db *gorm.DB, topologyID, actorID uint, input TopologyRevisionInput) (*model.TopologyRevision, error)
func DecodeRawNodeConfig ¶ added in v4.1.0
DecodeRawNodeConfig decodes a raw configuration an administrator sent inline or as a JSON string into an object; anything else is ErrRawNodeConfigNotObject.
func DefaultBackupConfig ¶ added in v4.1.0
func DefaultBackupConfig() model.BackupConfig
DefaultBackupConfig is the backup configuration the kernel creates when there is none.
func DeleteUserTx ¶ added in v4.1.0
DeleteUserTx deletes a user and its WireGuard peers in tx and records the revocation of its tokens; apply it with authn.Remember after the commit.
func DeriveSS2022ServerKey ¶
DeriveSS2022ServerKey 复刻老 XBoard `Helper::getServerKey($timestamp, $len)`: base64(substr(md5(unix秒的十进制字符串), 0, len))。md5 输出取 hex 字符串的前 len 个字符(不是字节), 再 base64。节点端 V2bX 用相同的 server_key, 两边必须一致。 导出供 handler 层 (UniProxy 节点拉配置) 复用, 保证订阅端和节点端算出的值一致。
func DropNodeCache ¶ added in v4.1.0
func DropNodeCache(id uint)
DropNodeCache forgets what the kernel caches about a proxy node: its row and the node list. The next read loads the rows as they are.
func EnsureAgentDiagnosticTaskSchema ¶
EnsureAgentDiagnosticTaskSchema creates the diagnostic task table if it does not exist. Called unconditionally at startup (including production) because AutoMigrate only runs in dev/test. It touches only the new table, never existing ones.
func EnsureForwardBridgeSchema ¶
EnsureForwardBridgeSchema creates the durable clean_agent bridge mapping table if it does not exist. Called unconditionally at startup (including production) because AutoMigrate only runs in dev/test. Idempotent and only touches this new table.
func EnsureForwardNodeMetricsPortColumn ¶
EnsureForwardNodeMetricsPortColumn adds the metrics_port column to the existing v2_forward_node table if it does not exist yet. Called unconditionally at startup (including production) because AutoMigrate only runs in dev/test. It touches only this one column on an existing table, never anything else.
func EnsureForwardRuntimeJobSchema ¶
EnsureForwardRuntimeJobSchema keeps runtime job invariants that GORM cannot express with model tags, especially the partial unique index for active jobs.
func EnsureKernelSchema ¶
EnsureKernelSchema only migrates new kernel-owned tables and is safe to run in production without touching legacy plugin-owned tables.
func EnsureNodeRuntimeHealthSchema ¶
EnsureNodeRuntimeHealthSchema adds the runtime-health columns used by WireGuard relay supervision. It is kept separate because production startup intentionally does not run the complete application AutoMigrate set.
func EnsureObservabilitySchema ¶
EnsureObservabilitySchema creates the latency bucket table if it does not exist. Called unconditionally at startup (including production) because AutoMigrate only runs in dev/test. It touches only the new observability table, never existing tables.
func EnsurePluginTrustRoot ¶
func EnsureStatsSchema ¶
EnsureStatsSchema creates or completes the traffic/stats tables: v2_server_log, v2_online_log, v2_stat_user, v2_stat_server. Called unconditionally at startup (including production) because AutoMigrate only runs in dev/test. Idempotent and limited to these tables; existing legacy tables are only expanded with missing columns/indexes.
func EnsureWireGuardPeerSchema ¶
EnsureWireGuardPeerSchema creates or upgrades only the WireGuard peer table. The server intentionally skips the full AutoMigrate set in production, so newly introduced runtime tables need an explicit idempotent schema hook.
func ExpireKernelOperations ¶
ExpireKernelOperations marks undispatched or in-flight work that has passed its deadline. A future supervisor worker may call this on a timer; read APIs also invoke it so stale intent is never presented as pending.
func ExtractPluginWebUIBundle ¶
func ExtractPluginWebUIBundle(manifest PluginManifest, artifact []byte) ([]byte, error)
func ForwardNodeAPIToken ¶ added in v4.1.0
ForwardNodeAPIToken is the token the kernel presents to a forward node's management API, through NodeX or gost, at the node's current address: its token when the address is the pinned endpoint (section 3.8), else ErrForwardNodeEndpointUnconfirmed.
func ForwardNodeHasToken ¶ added in v4.1.0
ForwardNodeHasToken reports whether a forward node holds a token, read through the credential split.
func ForwardUserResetRequestID ¶ added in v4.1.0
ForwardUserResetRequestID names an administrator's subscriber traffic reset through the Flux-style POST /api/v2/user/reset (type 1) in the subscriber request ledger, so a retried request is applied once. token identifies the HTTP request, as for AdminUserResetRequestID. (Until v4.2 the forward package's native handler derived the same id; since F5d the kernel serves the route alone.)
func GenerateForwardNodeToken ¶ added in v4.1.0
GenerateForwardNodeToken generates a forward node's API token, as the forward node creation does: 16 random bytes, hex encoded.
func GenerateWireGuardKeypair ¶
GenerateWireGuardKeypair exposes server-key generation to the authenticated admin workflow without persisting private material until the protocol is explicitly saved.
func GetPluginArtifact ¶
func GetPluginConfiguration ¶
GetPluginConfiguration returns the persisted document for one installation. An installation with no document has the deterministic empty-object default.
func HashKernelOperationConfig ¶
HashKernelOperationConfig returns the deterministic SHA-256 digest used in operation envelopes and persisted plugin configuration rows. The input is canonicalized first so semantically identical JSON documents share a hash.
func IdentityAuthoritative ¶ added in v4.1.0
IdentityAuthoritative reports whether identity owns credentials in state.
func IdentityAuthorityState ¶ added in v4.1.0
IdentityAuthorityState returns the identity authority state; no row means the kernel.
func InitAdmin ¶
InitAdmin creates the first administrator when the database has none. It creates nothing and returns ErrAdminPasswordRequired when no password is configured.
func InitDefaultAuthKeyFromEnv ¶
func InitDefaultAuthKeyFromEnv()
InitDefaultAuthKeyFromEnv 从环境变量初始化默认授权密钥 环境变量: NODE_DEFAULT_AUTH_KEY 如果设置了该环境变量:
- 如果密钥内容已存在 → 跳过
- 如果存在同名默认密钥但内容不同 → 删除旧的,创建新的
- 如果不存在 → 创建
Note: 改变 AuthKey 只会影响新节点注册,已注册节点使用 APIKey 通信,不受影响
func InitSubscriptionDefaults ¶
func InitSubscriptionDefaults()
InitSubscriptionDefaults 初始化默认订阅分组和模板
func InviteCodeLockKeys ¶ added in v4.1.0
InviteCodeLockKeys are the two keys of a user's invite code lock: the class and the user id. A user id beyond 31 bits shares its key with another user's, which only makes their generations wait for each other.
func IsAgentPluginOperation ¶
IsAgentPluginOperation reports whether an operation has a concrete Agent Supervisor implementation. Topology operations remain mediated through their concrete plugin lifecycle operations.
func IsForwardDiagnosticCheck ¶ added in v4.2.0
IsForwardDiagnosticCheck reports whether action is a forward check.
func IsNodeSecretKey ¶ added in v4.1.0
IsNodeSecretKey reports whether a key of a node protocol's settings, or of a node's raw configuration, names a secret: Reality's and TLS's private_key (privateKey), WireGuard's server_private_key and preshared_key, Shadowsocks' server_key, psk and password, the Hysteria2 obfs-password and auth, and any other *_key, password, passwd, pass, secret, token, credential or seed. Public keys, Reality's short_id and the paths of key files (key_file, wss_key_file) are not secrets. The rule is nodesecrets.IsSecretKey, which also places the secrets the credential split moves.
func IsSuperAdmin ¶ added in v4.1.0
IsSuperAdmin reports whether userID may switch route modes. The kernel has no separate super-administrator role, so this is its strictest administrator check, read from the database rather than the token: an administrator (is_admin) who is not staff and not banned. A demoted or banned administrator loses the right at once, not when the token expires.
func IsWireGuardExitProtocol ¶
func IsWireGuardExitProtocol(protocol *model.NodeProtocol) bool
IsWireGuardExitProtocol identifies the overseas relay role. Exit nodes do not terminate user WireGuard peers, so they must neither allocate peer keys, appear in user subscriptions, nor receive user runtime metadata.
func IssueForwardNodeTokenTx ¶ added in v4.1.0
IssueForwardNodeTokenTx writes a forward node's token to its row and the split tables, which pin it to the node's management endpoint (nodesecrets). A token that replaces another revokes the node's agent certificates (credentials_replaced), as the forward node update does. It reports whether a token was replaced.
func IssueProxyNodeCredentialsTx ¶ added in v4.1.0
func IssueProxyNodeCredentialsTx(tx *gorm.DB, nodeID uint, credentials ProxyNodeCredentials, replaced bool) error
IssueProxyNodeCredentialsTx writes a proxy node's credentials to its row and the split tables. With replaced, the node's agent certificates and enrollments are revoked (credentials_replaced): an agent enrolled with the old key must enroll again.
func IssueRegistrationKeyTx ¶ added in v4.1.0
func IssueRegistrationKeyTx(tx *gorm.DB, name string, expireAt *int64) (*model.AuthorizedKey, string, error)
IssueRegistrationKeyTx creates a node registration key and returns its row and the key, which is shown once. expireAt ends the key; nil never.
func KeepNodeRawConfig ¶ added in v4.1.0
KeepNodeRawConfig returns an incoming raw configuration with the stored values of the secrets it sends as NodeSecretPlaceholder (see KeepNodeSecretsJSON).
func KeepNodeSecretsJSON ¶ added in v4.1.0
KeepNodeSecretsJSON returns an incoming node protocol setting or raw configuration (JSON text) in which every secret sent as NodeSecretPlaceholder has its stored value (an empty string when nothing is stored), so an administrator can save what a masked answer showed without retyping its secrets. A placeholder sent for the whole value keeps the whole stored value. Arrays are matched by position.
func KeepSystemConfigFields ¶ added in v4.1.0
KeepSystemConfigFields returns incoming, a value about to be stored under key, in which every masked field sent as SensitiveSystemConfigPlaceholder has the value stored before ("" when nothing is stored), so an administrator can save what a masked answer showed without retyping its secrets. The placeholder sent for the whole value keeps the whole stored value. kept reports whether a stored secret was kept. The rest of the text is kept as it is.
func LegacyTopologyObservedHealthJSON ¶
func LegacyTopologyObservedHealthJSON() string
LegacyTopologyObservedHealthJSON is used only by the pre-executor compatibility bridge. Its Agent StateJson is intentionally discarded: that schema was never a public contract and may contain plugin-defined details.
func LoadBackupConfig ¶ added in v4.1.0
func LoadBackupConfig(db *gorm.DB) (*model.BackupConfig, error)
LoadBackupConfig reads the first backup configuration row, creating it with the defaults when there is none.
func LoadVerifiedPluginCompatibilityRoutes ¶
func LoadVerifiedPluginCompatibilityRoutes(db *gorm.DB, release model.PluginRelease, publicKey ed25519.PublicKey) ([]byte, error)
LoadVerifiedPluginCompatibilityRoutes returns the immutable compatibility declaration embedded in a signed v2 Control artifact. Callers still decide whether the corresponding installation is active; this helper establishes that the declaration itself is bound to the stored release and artifact.
func LoadVerifiedPluginWebUIAsset ¶
func LoadVerifiedPluginWebUIAsset(db *gorm.DB, release model.PluginRelease, manifest PluginManifest) (*model.PluginWebUIAsset, error)
func LockNodePluginLifecycleTx ¶
func LockNodePluginLifecycleTx(tx *gorm.DB, nodeID uint, pluginID string) (*model.NodePluginLifecycle, error)
LockNodePluginLifecycleTx acquires the aggregate lock without recalculating desired state. Mutating handlers use it before locking assignment rows so all callers follow the same lifecycle -> assignment lock order.
func LockPluginInstallationTarget ¶
LockPluginInstallationTarget must be called inside the transaction that validates and mutates plugin installation intent. The shared target row closes races where two packages could otherwise pass dependency/conflict checks against the same stale enabled set.
func LockUserInviteCodes ¶ added in v4.1.0
LockUserInviteCodes takes the user's invite code lock until tx ends, on PostgreSQL; on SQLite it does nothing.
func MaskAuthorizedKeys ¶ added in v4.1.0
func MaskAuthorizedKeys(keys []model.AuthorizedKey)
MaskAuthorizedKeys masks registration keys for an administrator's answer. A key is shown once, in the answer that generates it; a node registers with it by its hash.
func MaskSystemConfigFields ¶ added in v4.1.0
MaskSystemConfigFields returns value, the JSON object stored under key, with each of its masked fields that has a value (anything but null and a blank string) replaced by SensitiveSystemConfigPlaceholder. The rest of the text is kept as it is. A key without masked fields, a blank value and a JSON value that is not an object are returned unchanged; a value that is not JSON is replaced whole, since its secret cannot be told apart.
func MaskSystemConfigValue ¶
MaskSystemConfigValue is a value as an administrator's answer shows it: the placeholder for a sensitive key with a value, "" for one without, and any other value with its masked fields masked (MaskSystemConfigFields).
func MaterializePluginControlArtifact ¶
func MaterializePluginControlArtifact(db *gorm.DB, publicKey ed25519.PublicKey, pluginID, version, destinationRoot string) (pluginhost.ArtifactRef, error)
MaterializePluginControlArtifact writes the verified immutable release bytes and the signed v2 Control entrypoint into a private caller-owned directory. Task 3's lifecycle dispatcher consumes the resulting ArtifactRef; it still owns process supervision and never interprets package metadata itself.
func MigratePackageHost ¶
func MigratePackageHost(ctx context.Context, db *gorm.DB, manager *pluginhost.Supervisor, migrationRunID uint, input pluginhost.MigrationInput) (pluginhost.MigrationOutput, error)
MigratePackageHost is the only public orchestration path that can attach a health fence to a migration run. Requiring the concrete Supervisor prevents callers from substituting an arbitrary MigrationManager that fabricates a successful health result.
func NewSubscriberUser ¶ added in v4.1.0
NewSubscriberUser returns a new v2_user row with fresh node UUID and subscription token, as registration creates it.
func NodeHeartbeatStatus ¶ added in v4.1.0
NodeHeartbeatStatus is the status column a node's heartbeat writes: online, unless an administrator disabled the node. A heartbeat proves that the node's software runs; it never re-enables a disabled node. A pending node (never seen yet) becomes online, as before.
func NodeOpsCapabilities ¶ added in v4.1.0
func NodeOpsCapabilities() []string
NodeOpsCapabilities are the five KernelNodeOps family capabilities, in the order of the contract's OperationFamily enum.
func NodeTrafficBucketBounds ¶ added in v4.2.0
func NodeTrafficBucketBounds(granularity string, since, until, now time.Time) (time.Time, time.Time, error)
NodeTrafficBucketBounds aligns a requested window to the buckets of granularity: since rounds down to a bucket start, until up to a bucket boundary; a zero until is the end of the current bucket and a zero since the 24 hours (hour) or 30 days (day) before until. It returns ErrNodeTrafficWindow for an unknown granularity, an empty or reversed window, or one of more than MaxNodeTrafficHours hours or MaxNodeTrafficDays days.
func NormalizeForwardRuntimeBackend ¶ added in v4.1.0
NormalizeForwardRuntimeBackend answers the canonical name of a runtime backend (iptables_ansible is kept as named) and whether value names one.
func NormalizeNodeLogLevel ¶
func NormalizeNodeType ¶
NormalizeNodeType 归一化节点类型别名 (v2ray/vmess-aead → vmess)。
func OrderPaymentRequestID ¶ added in v4.1.0
OrderPaymentRequestID names a payment's order completion in the request ledger (v4_kernel_subscriber_request).
func PackageIndexMigrationID ¶ added in v4.1.0
PackageIndexMigrationID names the ledger run that applies a whole migration index, keyed by the index digest.
func PackageMigrationStepsDigest ¶ added in v4.1.0
func PackageMigrationStepsDigest(steps []pluginhost.MigrationStep) string
PackageMigrationStepsDigest is the validation digest a host must report after applying steps; see packagestoresdk.StepsDigest.
func PackageReleaseAtLeast ¶ added in v4.1.0
PackageReleaseAtLeast reports whether version is a semantic version at least minimum ("4.1.0" is above "4.1.0-rc.5"). A version that does not parse is not.
func PackageReportRefusal ¶ added in v4.2.0
PackageReportRefusal returns the reason of a refusal, or "" for any other error (one the kernel could not record for now).
func PackageReportStale ¶ added in v4.2.0
PackageReportStale reports whether a report of kind observed at observedAt is stale at now.
func PackageRouteCatalog ¶ added in v4.1.0
func PackageRouteCatalog() (map[string]RouteCatalogEntry, error)
PackageRouteCatalog returns the embedded package extraction map by route id: which routes have a native implementation (native-flagged), which only the legacy one (bridged) and which stay in the kernel (kernel-owned).
func PackageRouteDefaultPolicy ¶ added in v4.1.0
func PackageRouteDefaultPolicy() string
PackageRouteDefaultPolicy returns the process's default policy, rehearsed unless SetPackageRouteDefaultPolicy chose legacy.
func PackageRouteDefaultsSummary ¶ added in v4.1.0
PackageRouteDefaultsSummary describes the process policy for the startup log: the policy, and how many routes of how many packages default to native under it (for releases at least their min_version).
func ParseOnlineData ¶
ParseOnlineData 解析在线数据
func ParsePluginMigrationIndex ¶ added in v4.1.0
func ParsePluginMigrationIndex(manifest PluginManifest, artifact []byte) ([]pluginhost.MigrationStep, error)
ParsePluginMigrationIndex verifies the signed migration index of a package artifact and returns its steps in order. The index must match the manifest digest, name the manifest's package and version, and every step script must exist in the artifact with the declared digest.
func ParseTrafficData ¶
ParseTrafficData 解析流量数据
func PlanAssignmentRequestID ¶ added in v4.1.0
PlanAssignmentRequestID names an administrator's plan assignment in the subscriber request ledger (v4_kernel_subscriber_request), so a retried request is applied once. token identifies the HTTP request: its Idempotency-Key, else its request id. A new request is a new grant, as in v2. The plan package's native route derives the same id (packages/plan/native.AssignRequestID), so a retry is recognized whichever side serves it.
func PlanTopologyDeployment ¶
func PlanTopologyDeployment(db *gorm.DB, input TopologyDeploymentPlanInput) (*model.TopologyDeployment, []model.TopologyDeploymentStep, error)
PlanTopologyDeployment compiles the immutable graph into deployment steps. It does not mutate an active revision or create any Agent work.
func PluginAPIPermission ¶
func PluginControlBridgeRouteID ¶
PluginControlBridgeRouteID turns a signed Control route into a stable, package-bridge-safe operation name. The original route remains kernel-owned request metadata; package processes never choose it themselves.
func PluginRuntimeIsRemote ¶ added in v4.1.0
PluginRuntimeIsRemote adapts PluginRuntimeOf for the host supervisor.
func PluginRuntimeOf ¶ added in v4.1.0
PluginRuntimeOf returns the runtime of a Control package: remote only when a row selects it.
func PluginTrustRootKeyID ¶
func PluginWebUIAssetURL ¶
func ProxyNodeHasCredentials ¶ added in v4.1.0
ProxyNodeHasCredentials reports whether a proxy node holds an API key and a shared secret, read through the credential split.
func PurgeCompletedAssignmentDeletes ¶
func PurgeCompletedAssignmentDeletes(tx *gorm.DB, lifecycle *model.NodePluginLifecycle, chain *AgentAssignmentOperationChain) error
PurgeCompletedAssignmentDeletes is used by handlers when dispatch is explicitly disabled and the observed plugin is already inactive.
func RaiseNodeOperationRevision ¶ added in v4.2.0
RaiseNodeOperationRevision raises the stored desired revision of nodeID to at least revision, so the next allocation is above it. An Agent that connects reports the revision it last applied; after a Control restart it can be above the cursor.
func ReconcileAgentAssignments ¶
ReconcileAgentAssignments resumes enrolled lifecycle rows. It does not scan legacy generation-zero assignments, preserving the opt-in migration gate.
func RecordMigrationCheckpoint ¶
func RecordMigrationCheckpoint(db *gorm.DB, migrationRunID uint, checkpoint PackageMigrationCheckpoint) (*model.PackageMigrationRun, error)
RecordMigrationCheckpoint durably records an opaque host reply. It cannot activate a route; the health proof is recorded only by the service-owned migration coordinator after the supervisor returns successfully.
func RecordNodePluginOperationSuccessTx ¶
func RecordNodePluginOperationSuccessTx(tx *gorm.DB, operation model.KernelOperation) error
RecordNodePluginOperationSuccessTx captures the version actually selected by the Agent, so later disable/delete never guesses from a stale role row.
func RecordPackageValidation ¶
func RecordPackageValidation(db *gorm.DB, input model.PackageValidationResult) (*model.PackageValidationResult, error)
RecordPackageValidation accepts only a completed migration checkpoint and creates the initial one-percent route generation. The digest remains opaque to the kernel.
func RedactNode ¶ added in v4.1.0
RedactNode masks a node's raw configuration and the secrets of its loaded protocols for an administrator's answer (see RedactNodeProtocol). The node's API key and shared secret are never serialized (json:"-").
func RedactNodeProtocol ¶ added in v4.1.0
func RedactNodeProtocol(protocol *model.NodeProtocol)
RedactNodeProtocol masks the secrets in a node protocol's settings for an administrator's answer. It changes the protocol it is given, so it is for a row read for that answer only, never one that is saved afterwards. The protocol's node, when loaded, has its raw configuration masked too.
func RedactNodeProtocols ¶ added in v4.1.0
func RedactNodeProtocols(protocols []model.NodeProtocol)
RedactNodeProtocols masks the protocols of an administrator's answer.
func RedactNodeSecretsJSON ¶ added in v4.1.0
RedactNodeSecretsJSON replaces the secret values of a node protocol setting or a raw configuration (JSON text) with NodeSecretPlaceholder. A string or array under a secret key is replaced whole; an object's own keys are checked, and so are the objects in arrays. A value without a secret is returned unchanged, and one that is not JSON is replaced whole, since it cannot be told apart.
The rule is nodesecrets.Redact, which also writes the documents a finalized table keeps (section 4.4), so the stored redacted document and this answer are the same bytes.
func RefreshAgentPluginInstallationObservedState ¶
RefreshAgentPluginInstallationObservedState projects node lifecycle state in a separate, consistently ordered transaction. Lifecycle mutations must not call this while holding an aggregate lock because global installation writes use target -> installation -> lifecycle ordering.
func RegisterPluginRelease ¶
func RegisterPluginRelease(db *gorm.DB, manifestJSON, signature string, publicKey ed25519.PublicKey) (*model.PluginRelease, error)
RegisterPluginRelease admits only a manifest signed by the configured AnixOps trust root and records the current exclusive trust-root fingerprint. Artifact bytes are uploaded separately and must match the signed manifest hash before an install can be enabled.
func RenumberPendingNodeOperations ¶ added in v4.2.0
func RenumberPendingNodeOperations(db *gorm.DB, nodeID uint, operationID string, floor int64) (int64, error)
RenumberPendingNodeOperations moves the durable operation operationID, which the Agent control stream refused because its revision is not above the last revision sent on the node, and the pending operations behind it onto revisions above both the stored cursor and floor, keeping their order, and returns the operation's new revision. A durable operation takes its revision when it is created; a one-off stream operation sent after that takes a higher one, and the Agent supersedes anything at or below the revision it observed, so the older number can never be sent again. The operation goes back to pending so the dispatcher sends it with its new revision. Only an operation with no earlier active operation on the node qualifies, which means every pending operation behind it has never been sent.
func ReportNodeSecretFindings ¶ added in v4.1.0
func ReportNodeSecretFindings(findings []NodeSecretFinding)
ReportNodeSecretFindings counts and logs each finding of a configuration build (anixops_node_secrets_invalid_total, once per subject in the log). It excludes nothing.
func RequestTopologyDeploymentApply ¶
func RequestTopologyDeploymentApply(db *gorm.DB, deploymentID uint, _ time.Time) (*model.TopologyDeployment, error)
RequestTopologyDeploymentApply makes a plan eligible for the feature-gated worker. It is idempotent while already applying but never reopens terminal deployments, preserving an audit trail for every revision attempt.
func RequestTopologyDeploymentRollback ¶
func RequestTopologyDeploymentRollback(db *gorm.DB, deploymentID uint, at time.Time) (*model.TopologyDeployment, error)
RequestTopologyDeploymentRollback stops expansion and schedules durable reverse-order compensation. It is safe to call before any operation has dispatched; such a deployment simply reaches rolled_back with skipped steps.
func ResetLoginRateLimiterForTest ¶
func ResetLoginRateLimiterForTest()
ResetLoginRateLimiterForTest forgets every login, registration and subscription reset attempt.
func ResetStatsServiceForTest ¶ added in v4.1.0
func ResetStatsServiceForTest()
ResetStatsServiceForTest drops the shared StatsService, which keeps the database it was first built with, so a test that opens a new database gets a service on it.
func ResolveActivePluginWebUIAsset ¶
func ResolveActivePluginWebUIAsset(db *gorm.DB, publicKey ed25519.PublicKey, actorID uint, legacyAdmin bool, pluginID, version, bundleSHA256 string) (*model.PluginWebUIAsset, error)
ResolveActivePluginWebUIAsset binds an immutable asset URL to the currently active control installation and to the requesting actor. Stored signatures, release metadata, artifact bytes and the extracted bundle are revalidated on every request so disabling or replacing an installation invalidates old URLs.
func ResolveEffectivePackageRouteModes ¶ added in v4.1.0
func ResolveEffectivePackageRouteModes(db *gorm.DB, packageID, version string, stored map[string]string) (map[string]string, map[string]string, error)
ResolveEffectivePackageRouteModes returns a package's effective route modes and where each comes from. It is what every reader that hands modes to a package host, or shows them, uses: the bridge's GetPackageConfig and the route-mode administration. In order:
- a stored mode wins, legacy included;
- identity group A follows the identity authority (ResolvePackageRouteModes);
- a route of the default set (config/package-route-defaults.json) is native when the policy is rehearsed, the installed release (version) is at least the package's min_version and the extraction map still lists the route as native-flagged for the package;
- anything else is legacy.
The returned modes name every route that is not legacy plus the stored ones; sources name the stored, identity and default-set routes (any other route is RouteModeSourceUnset).
func ResolvePackageRouteModes ¶ added in v4.1.0
func ResolvePackageRouteModes(db *gorm.DB, packageID string, stored map[string]string) (map[string]string, error)
ResolvePackageRouteModes returns a package's effective route modes from its stored route-mode map, for identity group A. Every reader resolves through it (the configuration check directly; the package host's configuration and the route-mode administration through ResolveEffectivePackageRouteModes, which adds the rehearsed defaults), so the rule below holds for any group A route, today's and future ones: identity-platform's group A routes that the stored map does not name are native while identity is authoritative (state identity or finalized), because group A is native exactly then. An installation whose map predates a route added to group A (the cutover wrote only the routes it knew) therefore stays consistent without an operator writing the new key. A route the map names keeps its stored mode, legacy included; in the kernel and importing states a missing route is legacy, as for every other package. The stored map is not changed.
func RevokeCleanAgentTx ¶ added in v4.1.0
RevokeCleanAgentTx is RevokeAgent in the caller's transaction: the agent is marked revoked and its split row follows. RevokeCredential runs it in the operation's transaction. An agent that does not exist is gorm.ErrRecordNotFound; one already revoked is revoked again.
func RevokeRegistrationKeyTx ¶ added in v4.1.0
RevokeRegistrationKeyTx deletes a registration key with its split rows. It reports whether a key was deleted; a key already gone is no error.
func RollbackPackageGeneration ¶
func RollbackPackageGeneration(db *gorm.DB, generationID uint, reason string) (*model.PackageRouteGeneration, error)
RollbackPackageGeneration retires the current generation and returns its verified predecessor. Both the reason and any retained backup reference are recorded transactionally; no package-owned table is touched.
func RouteModeActorName ¶ added in v4.1.0
RouteModeActorName is the audit name of a signed-in administrator: the e-mail, or "user:<id>".
func RunForwardRuntimeJobPayloadScrub ¶ added in v4.1.0
RunForwardRuntimeJobPayloadScrub is the start-up pass: it scrubs and logs counts only.
func ScrubForwardRuntimeJobPayload ¶ added in v4.1.0
ScrubForwardRuntimeJobPayload removes every credential from a stored job payload: every key IsNodeSecretKey marks, at any depth, is removed with its value, as a new payload omits it. It reports whether anything was removed. A payload that is not JSON is returned as it is. The key is removed, not masked: the placeholder would read as a token present to NodeX and the agents, and a cleared value would be scanned again at the next start.
func ScrubForwardRuntimeJobPayloads ¶ added in v4.1.0
ScrubForwardRuntimeJobPayloads rewrites the payloads of the runtime jobs written before NO-7 that still carry a token, in batches, and answers how many rows it changed. It is idempotent: a scrubbed payload no longer matches, so a start after the first pass reads nothing. It runs at start in the singleton worker process (cmd/server), before the job executors serve a row.
func SetPackageRouteDefaultPolicy ¶ added in v4.1.0
func SetPackageRouteDefaultPolicy(policy string)
SetPackageRouteDefaultPolicy sets the default policy (package_routes.default_mode) for this process. Anything but legacy means rehearsed, the default.
func SetPackageRouteModesTx ¶ added in v4.1.0
func SetPackageRouteModesTx(tx *gorm.DB, publicKey ed25519.PublicKey, installationID uint, modes map[string]string, actorID uint) (*model.PluginConfiguration, error)
SetPackageRouteModesTx sets route modes in a Control installation's configuration inside tx, keeping the rest of the document. Legacy removes the route from the map, except for a route of the rehearsed default set (config/package-route-defaults.json), which keeps an explicit legacy so the default does not take it back. It fails with ErrPluginConfigurationConflict if the document changes concurrently.
func SetPluginRuntime ¶ added in v4.1.0
func SetPluginRuntime(ctx context.Context, db *gorm.DB, pluginID, runtime string, remoteEnabled bool, actorID uint) (*model.PluginRuntime, error)
SetPluginRuntime selects a package's runtime. It takes effect at the package's next lifecycle operation. Remote requires the module runtime and PostgreSQL, because module instances cannot share a SQLite file.
func SettingsCapability ¶ added in v4.1.0
SettingsCapability is the capability for access to namespace.
func SettingsGeneration ¶ added in v4.1.0
SettingsGeneration returns the namespace's current generation.
func ShadowSampleRoute ¶ added in v4.1.0
func ShadowSampleRoute(routeID string) (shadowsamples.RouteInfo, bool)
ShadowSampleRoute looks a route up in the package extraction map for the shadow sample collector: the package that owns it and its path template.
func StorePluginArtifact ¶
func StringifyConfigMap ¶
StringifyConfigMap 把 map[string]any 转成 map[string]string (proto 的 map<string,string> 字段需要)。数字按整数/浮点合理格式化, 避免 443 变 "443.000000"。
func SubscriptionGroupDeleteRequestID ¶ added in v4.1.0
SubscriptionGroupDeleteRequestID names the removal of a deleted group's members, as SubscriptionGroupGrantRequestID names a grant (packages/subscription/native.DeleteGroupRequestID).
func SubscriptionGroupGrantRequestID ¶ added in v4.1.0
func SubscriptionGroupGrantRequestID(userID, groupID uint, expireAt, transferEnable, nextRenewPrice *int64, token string) string
SubscriptionGroupGrantRequestID names an administrator's grant of a subscription group to a user in the subscriber request ledger (v4_kernel_subscriber_request), so a retried request is applied once. token identifies the HTTP request: its Idempotency-Key, else its request id. The digest also covers the granted fields, so a key reused for other values is another grant. The subscription package's native route derives the same id (packages/subscription/native.GrantRequestID), so a retry is recognized whichever side serves it.
func SubscriptionGroupRevokeRequestID ¶ added in v4.1.0
SubscriptionGroupRevokeRequestID names an administrator's removal of a user's subscription group, as SubscriptionGroupGrantRequestID names a grant (packages/subscription/native.RevokeRequestID).
func SubscriptionResetRateLimitKey ¶ added in v4.1.0
SubscriptionResetRateLimitKey is a user's key in the reset limiter.
func SyncAgentInstallationAssignments ¶
func SyncAgentInstallationAssignments(tx *gorm.DB, installation model.PluginInstallation, configRevision int64, queue bool, now time.Time) ([]*model.KernelOperation, error)
SyncAgentInstallationAssignments updates every matching assignment revision and aggregate generation in the caller's configuration transaction.
func SyncNodePluginLifecycle ¶
func SyncNodePluginLifecycle(tx *gorm.DB, nodeID uint, pluginID string, explicitRetry bool, _ time.Time) (*model.NodePluginLifecycle, bool, error)
SyncNodePluginLifecycle serializes every role of one node/plugin pair, computes aggregate desired state and optionally rearms an exhausted chain after an explicit administrator mutation.
func SystemConfigAuditContent ¶ added in v4.1.0
func SystemConfigAuditContent(cfg *model.SystemConfig, preserveExisting bool) string
SystemConfigAuditContent is the content of a system configuration audit entry.
func SystemConfigMaskedFields ¶ added in v4.1.0
SystemConfigMaskedFields returns the masked fields of key's value, none for most keys.
func TelegramWebhookSecret ¶ added in v4.2.1
TelegramWebhookSecret is the secret_token registered with setWebhook. Telegram sends it back in X-Telegram-Bot-Api-Secret-Token with every update. It is derived from the bot token, so the webhook keeps no extra state. Changing the token changes the secret: set the webhook again afterwards.
func TouchSettingsKey ¶ added in v4.1.0
func TouchSettingsKey(key string)
TouchSettingsKey bumps the generation of key's namespace, if any.
func UpdatePluginConfigurationWithValidatorAndHook ¶
func UpdatePluginConfigurationWithValidatorAndHook(db *gorm.DB, publicKey ed25519.PublicKey, installationID uint, rawConfig string, expectedRevision *int64, actorID uint, validator PluginConfigurationSemanticValidator, hook PluginConfigurationTxHook) (*model.PluginConfiguration, error)
func UpdateUserOnceTx ¶ added in v4.1.0
func UpdateUserOnceTx(tx *gorm.DB, requestID, method string, userID uint, updates map[string]any, now time.Time) (bool, *authn.Revocation, error)
UpdateUserOnceTx applies updates to an existing user through UpdateUserTx once per request id, recording it in the subscriber request ledger: a repeated id changes nothing and reports applied false. A user that does not exist is ErrUserNotFound, and nothing is recorded. The revocation, if any, is for authn.Remember after the commit. An empty request id applies every time.
func UpdateUserTx ¶ added in v4.1.0
UpdateUserTx updates a user in tx. When the change ends the user's sessions it also records the revocation and returns it; apply it with authn.Remember after the commit.
func UpdateUserTxWithTokenVersion ¶ added in v4.1.0
func UpdateUserTxWithTokenVersion(tx *gorm.DB, id uint, updates map[string]any, tokenVersion uint64) (*authn.Revocation, error)
UpdateUserTxWithTokenVersion is UpdateUserTx for a change identity made: tokenVersion, when positive, is the account's new token version, so the revocation ends identity tokens by version rather than by time.
func UserAliveCounts ¶ added in v4.2.0
UserAliveCounts counts each user's online IPs across all nodes: the sets UpdateOnlineStatus keeps per node and user (online:<type>:<node>:<user>), added up per user. Users without any are left out. It is the source of UniProxy alivelist and of the Agent Control stream's AliveList (alive.v1).
func UserSubscriptionResetRequestID ¶ added in v4.1.0
UserSubscriptionResetRequestID names a user's reset of their own subscription token in the subscriber request ledger, so a retried request is applied once: identity.user_reset_subscribe:<user>:<digest>, a digest of the request's Idempotency-Key (else its request id). The identity package's native handler derives the same id.
func ValidateAgentDiagnosticTask ¶
ValidateAgentDiagnosticTask 校验 action 是否在白名单内,并将 params 归一化为 仅包含该 action 允许的字段(多余字段被丢弃,数值做范围裁剪)。 返回的 error 可直接展示给管理员。
func ValidateForwardDiagnosticCheck ¶ added in v4.2.0
ValidateForwardDiagnosticCheck checks a forward check's parameters and answers them normalized: only the check's parameters, hop_index and generation as integers, timeout_ms clamped (ForwardCheckDefaultTimeoutMS when absent), target_policy public_only when absent.
func ValidateNodeProtocol ¶
func ValidateNodeProtocol(protocol *model.NodeProtocol) error
ValidateNodeProtocol validates the fields that affect node runtime. The existing protocol API accepts JSON strings for protocol-specific settings, so validation belongs in the service layer and covers both HTTP and gRPC callers that persist protocols.
func ValidatePluginAPIGrantPermissions ¶
ValidatePluginAPIGrantPermissions rejects malformed or cross-plugin grants before they enter the kernel authorization table.
func ValidatePluginDependencyExecutionPlan ¶
func ValidatePluginDependencyExecutionPlan(db *gorm.DB, plan *PluginDependencyExecutionPlan) error
ValidatePluginDependencyExecutionPlan verifies every selected artifact and validates conflicts against already-enabled packages outside the closure. Callers hold PluginTargetLock while invoking it and applying the plan.
func ValidatePluginReleaseTarget ¶
func ValidatePluginReleaseTarget(release model.PluginRelease, target string) error
func ValidateRegistrationEmail ¶
func ValidateRegistrationEmail(email string, policy RegistrationPolicy) error
func ValidateTrafficDelta ¶
func ValidateWireGuardRuntimeConfig ¶
ValidateWireGuardRuntimeConfig validates a raw node config after it has been decoded from JSON. Raw configs bypass NodeProtocol persistence, so they need the same runtime guard before UniProxy returns them to a node.
func VerifyPluginArtifact ¶
func VerifyPluginArtifact(manifest PluginManifest, artifact []byte) error
VerifyPluginArtifact checks the bytes fetched from the signed repository before they are handed to an installer. The manifest signature alone is not sufficient when an artifact is replaced at the transport layer.
func WithAgentLifecycleTransaction ¶
WithAgentLifecycleTransaction retries only SQLite writer-contention errors. PostgreSQL locking and all semantic errors are returned immediately.
func WithRetryableTransaction ¶
WithRetryableTransaction reruns the whole transaction only when SQLite reports transient writer contention. The mutation may run more than once, so it must keep side effects inside the transaction. Other databases and semantic failures return immediately.
func WithdrawDebitRequestID ¶ added in v4.1.0
WithdrawDebitRequestID names a withdrawal's debit of the commission balance in the subscriber request ledger (v4_kernel_subscriber_request). The affiliate package's native route uses the same id.
func WithdrawRefundCents ¶ added in v4.1.0
WithdrawRefundCents is what rejecting a withdrawal returns to the commission balance. Withdrawals are whole amounts; one stored with a fraction, possible before they had to be, is refunded its whole part, which is what its debit took on PostgreSQL: the driver truncated the amount bound to "commission_balance - ?".
func WithdrawRefundRequestID ¶ added in v4.1.0
WithdrawRefundRequestID names the refund of a rejected withdrawal, so a withdrawal is refunded once.
Types ¶
type ActorPluginAccess ¶
type ActorPluginAccess struct {
Unrestricted bool
LegacyAdmin bool
Permissions []string
RestrictedPlugins []string
// contains filtered or unexported fields
}
ActorPluginAccess is the kernel-authoritative plugin permission view for one actor. A legacy administrator remains unrestricted for plugins that have no explicit grant, while each plugin with at least one grant is evaluated fail-closed. This permits incremental migration of plugin permissions.
func NewFailClosedActorPluginAccess ¶
func NewFailClosedActorPluginAccess() *ActorPluginAccess
NewFailClosedActorPluginAccess is used when authentication has already committed but the optional plugin authorization lookup is temporarily unavailable. It never grants access and lets the caller return a valid session that can retry its profile fetch.
func ResolveActorPluginAccess ¶
func ResolveActorPluginAccess(db *gorm.DB, actorID uint, legacyAdmin bool) (*ActorPluginAccess, error)
ResolveActorPluginAccess reads enabled access-group memberships and their plugin_api grants. Permission arrays and truthy object entries are unioned, de-duplicated and sorted for deterministic API responses.
func (ActorPluginAccess) Allows ¶
func (access ActorPluginAccess) Allows(pluginID, permission string) bool
func (ActorPluginAccess) HasAnyPermission ¶
func (access ActorPluginAccess) HasAnyPermission(pluginID string) bool
func (ActorPluginAccess) PermissionMode ¶
func (access ActorPluginAccess) PermissionMode() string
func (ActorPluginAccess) ProfilePermissions ¶
func (access ActorPluginAccess) ProfilePermissions() []string
func (ActorPluginAccess) ProfileRestrictedPluginList ¶
func (access ActorPluginAccess) ProfileRestrictedPluginList() []string
ProfileRestrictedPluginList intentionally hides the catalog of configured plugin grants from non-administrators. They still receive their effective permissions, but not a cross-tenant enumeration of restricted plugins.
func (ActorPluginAccess) RestrictedPluginList ¶
func (access ActorPluginAccess) RestrictedPluginList() []string
type AgentAssignmentOperationChain ¶
type AgentAssignmentOperationChain struct {
Install *model.KernelOperation
Update *model.KernelOperation
Enable *model.KernelOperation
Disable *model.KernelOperation
}
func QueueAgentAssignmentLifecycle ¶
func QueueAgentAssignmentLifecycle(tx *gorm.DB, assignment model.NodeServiceAssignment, now time.Time) (*AgentAssignmentOperationChain, error)
QueueAgentAssignmentLifecycle remains the focused entry point used by tests and callers that have already mutated one assignment transactionally.
func QueueNodePluginLifecycle ¶
func QueueNodePluginLifecycle(tx *gorm.DB, lifecycle *model.NodePluginLifecycle, now time.Time) (*AgentAssignmentOperationChain, error)
QueueNodePluginLifecycle reuses a valid current chain before touching signed package metadata. Failed chains receive bounded retry epochs with backoff; successful or in-flight chains are never duplicated on periodic reconcile.
type AgentDiagnosticActionSpec ¶
AgentDiagnosticActionSpec 描述一个白名单诊断动作允许携带哪些参数,以及是否为变更类操作。
type AgentDiagnosticTaskService ¶
type AgentDiagnosticTaskService struct {
// contains filtered or unexported fields
}
AgentDiagnosticTaskService 负责白名单诊断任务的持久化,取代 AgentHandler 里原来的 taskResults sync.Map,使任务结果在面板进程重启后仍可查询。
func NewAgentDiagnosticTaskService ¶
func NewAgentDiagnosticTaskService(db *gorm.DB) *AgentDiagnosticTaskService
func (*AgentDiagnosticTaskService) CompleteTask ¶
func (s *AgentDiagnosticTaskService) CompleteTask(taskID string, nodeID uint, action string, success bool, output string, errMsg string, durationMS int64) error
CompleteTask 写入任务的最终执行结果。如果 task_id 尚无记录(例如 agent 直接 上报、面板端没有先建任务),则补建一条 completed/failed 记录,保持幂等可查询。
nodeID is the authenticated node that reports: it completes only its own tasks, and a task of another node is refused with ErrAgentDiagnosticTaskOfAnotherNode instead of being taken over.
func (*AgentDiagnosticTaskService) CreateTask ¶
func (s *AgentDiagnosticTaskService) CreateTask(taskID string, nodeID uint, action string, params map[string]any) (*model.AgentDiagnosticTask, error)
CreateTask 插入一条 pending 状态的诊断任务记录,params 必须已经过 ValidateAgentDiagnosticTask 归一化。
func (*AgentDiagnosticTaskService) GetTask ¶
func (s *AgentDiagnosticTaskService) GetTask(taskID string) (*model.AgentDiagnosticTask, error)
GetTask 按 task_id 查询单条任务。
func (*AgentDiagnosticTaskService) ListTasks ¶
func (s *AgentDiagnosticTaskService) ListTasks(nodeID uint, limit int) ([]model.AgentDiagnosticTask, error)
ListTasks 按可选的 node_id 过滤,返回最近的诊断任务历史(供管理页任务历史表使用)。
func (*AgentDiagnosticTaskService) MarkStatus ¶
func (s *AgentDiagnosticTaskService) MarkStatus(taskID string, status string) error
MarkStatus 更新任务的投递状态(如 dispatched),不改变最终结果字段。
func (*AgentDiagnosticTaskService) PullPendingTasks ¶
func (s *AgentDiagnosticTaskService) PullPendingTasks(nodeID uint) ([]model.AgentDiagnosticTask, error)
PullPendingTasks 取出该节点尚未下发 (status=pending) 的诊断任务,并原子标记为 dispatched,供 HTTP 轮询降级路径 (AgentGetTasks) 使用,避免并发重复下发。
type AgentNodeStatus ¶ added in v4.1.0
type AgentNodeStatus struct {
CPUUsage float64
MemoryUsage float64
DiskUsage float64
Uptime int64
RuntimeHealthy bool
RuntimeError string
}
AgentNodeStatus is a NodeStatus from the Agent Control stream (reports.v1).
type AgentPluginInstallConfig ¶
type AgentPluginInstallConfig struct {
APIVersion string `json:"api_version"`
PluginID string `json:"plugin_id"`
Version string `json:"version"`
Artifact AgentPluginArtifactAddress `json:"artifact"`
Manifest AgentPluginManifestAddress `json:"manifest"`
}
type AgentPluginReleaseDownload ¶
type AgentPluginReleaseDownload struct {
Release model.PluginRelease
Manifest PluginManifest
ManifestData []byte
Artifact model.PluginArtifact
ManifestHash string
}
AgentPluginReleaseDownload is verified immediately before a node-facing response is written. Data is intentionally kept out of JSON response types.
func LoadAgentPluginArtifactBlob ¶
func LoadAgentPluginArtifactBlob(db *gorm.DB, metadata *AgentPluginReleaseDownload) (*AgentPluginReleaseDownload, error)
LoadAgentPluginArtifactBlob is intentionally separate from authorization and content-address validation. Node-facing handlers call it only after the bounded metadata path has accepted the exact immutable address.
func LoadAuthorizedAgentPluginMetadata ¶
func LoadAuthorizedAgentPluginMetadata(db *gorm.DB, nodeID uint, pluginID, version string) (*AgentPluginReleaseDownload, error)
LoadAuthorizedAgentPluginMetadata verifies assignment, global installation, official signature and persisted size metadata without loading the package blob. Reconcile and manifest requests must stay on this bounded path.
func (*AgentPluginReleaseDownload) ValidateArtifactAddress ¶
func (download *AgentPluginReleaseDownload) ValidateArtifactAddress(sha256Hex string, size int64) error
func (*AgentPluginReleaseDownload) ValidateManifestAddress ¶
func (download *AgentPluginReleaseDownload) ValidateManifestAddress(sha256Hex string, size int64) error
type AuthService ¶
type AuthService struct{}
func NewAuthService ¶
func NewAuthService() *AuthService
func (*AuthService) Authenticate ¶
func (s *AuthService) Authenticate(email, password string) (*model.User, error)
Authenticate validates login credentials and account state without issuing a token.
func (*AuthService) IssueToken ¶
IssueToken signs a JWT for an already authenticated user.
func (*AuthService) RegisterWithInvite ¶
func (s *AuthService) RegisterWithInvite(email, password, inviteCode string, cfg *config.Config) (string, *model.User, error)
RegisterWithInvite creates a user and optionally consumes an invite code.
type BackupService ¶
type BackupService struct {
// contains filtered or unexported fields
}
BackupService runs backups. It keeps the backup configuration in memory and reloads it when the backup settings namespace changed (SettingsGeneration), so a change made through KernelSettings or another BackupService reaches it before its next backup.
func NewBackupService ¶
func NewBackupService(db *gorm.DB) *BackupService
func (*BackupService) CleanupOldBackups ¶
func (s *BackupService) CleanupOldBackups() error
func (*BackupService) CreateBackup ¶
func (s *BackupService) CreateBackup(backupType string, createdBy *uint) (*model.BackupRecord, error)
func (*BackupService) DeleteBackup ¶
func (s *BackupService) DeleteBackup(id uint) error
func (*BackupService) GetBackupStats ¶
func (s *BackupService) GetBackupStats() (map[string]any, error)
func (*BackupService) GetConfig ¶
func (s *BackupService) GetConfig() (*model.BackupConfig, error)
GetConfig returns the backup configuration: the copy in memory while the backup settings namespace has not changed since it was loaded, else the first row, created with the defaults when there is none.
func (*BackupService) ListBackups ¶
func (s *BackupService) ListBackups(page, pageSize int) ([]model.BackupRecord, int64, error)
func (*BackupService) RestoreBackup ¶
func (s *BackupService) RestoreBackup(id uint) error
func (*BackupService) UpdateConfig ¶
func (s *BackupService) UpdateConfig(cfg *model.BackupConfig) error
UpdateConfig saves cfg and makes it the configuration in memory. Every other copy of the backup settings reloads.
type CreateOrderParams ¶
type CreateOrderParams struct {
UserID uint
PlanID uint
Period string // month, quarter, half_year, year, two_year, three_year, onetime
CouponID *uint
}
CreateOrderParams 创建订单参数
type CreateRuleRequest ¶
type CreateRuleRequest struct {
Name string `json:"name"`
RelayNodeID uint `json:"relay_node_id"`
ExitNodeID uint `json:"exit_node_id"`
Protocol string `json:"protocol"`
TargetHost string `json:"target_host"`
TargetPort int `json:"target_port"`
SpeedLimit *int64 `json:"speed_limit"`
TrafficLimit *int64 `json:"traffic_limit"`
ExpireTime *time.Time `json:"expire_time"`
}
CreateRuleRequest is the request payload for user-owned rule creation.
type DashboardStats ¶
type DashboardStats struct {
// 用户统计
TotalUsers int64 `json:"total_users"`
ActiveUsers int64 `json:"active_users"`
ExpiredUsers int64 `json:"expired_users"`
BannedUsers int64 `json:"banned_users"`
TodayNewUsers int64 `json:"today_new_users"`
// 订单统计
TotalOrders int64 `json:"total_orders"`
PendingOrders int64 `json:"pending_orders"`
PaidOrders int64 `json:"paid_orders"`
TotalRevenue int64 `json:"total_revenue"` // 总收入 (分)
MonthlyIncome int64 `json:"monthly_income"` // 月收入 (分)
TodayIncome int64 `json:"today_income"` // 今日收入 (分)
// 节点统计
TotalNodes int64 `json:"total_nodes"`
ActiveNodes int64 `json:"active_nodes"`
OnlineUsers int64 `json:"online_users"`
// 流量统计
TotalTrafficUsed int64 `json:"total_traffic_used"` // 总已用流量 (字节)
TodayTraffic int64 `json:"today_traffic"` // 今日流量 (字节)
// 缓存信息
CachedAt time.Time `json:"cached_at"`
}
DashboardStats 仪表盘统计数据
type DiagnosisOutcome ¶
type DiagnosisOutcome struct {
Success bool `json:"success"`
Description string `json:"description"`
NodeName string `json:"nodeName"`
NodeID string `json:"nodeId"`
TargetIP string `json:"targetIp"`
TargetPort int `json:"targetPort,omitempty"`
Message string `json:"message,omitempty"`
AverageTime float64 `json:"averageTime,omitempty"`
PacketLoss float64 `json:"packetLoss,omitempty"`
}
type DiagnosisProbes ¶ added in v4.1.0
type DiagnosisProbes struct {
// Dial opens a probe's TCP connection within timeout.
Dial func(ctx context.Context, network, address string, timeout time.Duration) (net.Conn, error)
// Lookup resolves the host name of a target a user chose.
Lookup func(ctx context.Context, host string) ([]netip.Addr, error)
// Concurrency bounds the probes in flight; DefaultDiagnosisConcurrency
// when zero.
Concurrency int
}
DiagnosisProbes is how a diagnosis reaches the network. The zero value dials with net.Dialer and resolves names with the system resolver, as the legacy routes do; tests replace both.
func (DiagnosisProbes) ProbeEndpoint ¶ added in v4.1.0
func (p DiagnosisProbes) ProbeEndpoint(ctx context.Context, node *model.ForwardNode) (*HealthCheckResult, error)
ProbeEndpoint dials node's service port (host:port), as the forward node check does: online with the latency when it connects, offline with the dial's error when it does not. A check whose ctx ended is no check: ctx's error is returned.
func (DiagnosisProbes) PublicHost ¶ added in v4.1.0
PublicHost resolves the host of a probe Control runs for a user and answers the address to connect to, or the refusal (publicProbeAddress): loopback, private and other non-public addresses are refused.
type DiagnosisReport ¶
type DiagnosisReport struct {
ForwardName string `json:"forwardName"`
Timestamp int64 `json:"timestamp"`
Results []DiagnosisOutcome `json:"results"`
}
type EffectiveAccess ¶
type EffectiveAccess struct {
ScopeID string `json:"scope_id"`
Groups []model.AccessGroup `json:"groups"`
Grants []model.ResourceGrant `json:"grants"`
Quotas []model.QuotaPolicy `json:"quotas"`
}
func ResolveEffectiveAccess ¶
func ResolveEffectiveAccess(db *gorm.DB, userID uint, planID *uint, scopeID string) (*EffectiveAccess, error)
ResolveEffectiveAccess returns the allow-union of direct and plan-derived memberships for one scope. Calling it once per scope keeps counters and quota policy ownership isolated.
type EndpointCheck ¶ added in v4.1.0
type EndpointCheck struct {
NodeID uint
// Node is the node's row; nil when the node does not exist.
Node *model.ForwardNode
// Result is the check's result; nil when it did not run or failed.
Result *HealthCheckResult
// Err is why there is no result: gorm.ErrRecordNotFound for a node that
// does not exist, or the check's error.
Err error
}
EndpointCheck is one node's check in CheckEndpoints.
type ForwardAgentBridgeService ¶
type ForwardAgentBridgeService struct {
// contains filtered or unexported fields
}
ForwardAgentBridgeService handles result write-back for clean_agent bridge jobs. It is shared by the agent result handler so that job/forward state transitions stay identical to the local ansible executor semantics.
func NewForwardAgentBridgeService ¶
func NewForwardAgentBridgeService(db *gorm.DB) *ForwardAgentBridgeService
func (*ForwardAgentBridgeService) CompleteJob ¶
func (s *ForwardAgentBridgeService) CompleteJob(taskID string, success bool, output, errMsg string) (alreadyDone bool, err error)
CompleteJob writes an agent-reported result back to the runtime job, the forward runtime state, and marks the bridge mapping completed. It is idempotent: a mapping already in a terminal state is a no-op (duplicate/late reports return alreadyDone=true).
func (*ForwardAgentBridgeService) LookupBridgeTask ¶
func (s *ForwardAgentBridgeService) LookupBridgeTask(taskID string) (*model.ForwardAgentBridgeTask, error)
LookupBridgeTask returns the durable bridge mapping for a given agent task_id. Returns (nil, nil) when the task_id is not a bridge task (e.g. an admin memory task).
type ForwardAgentBridgeWorker ¶
type ForwardAgentBridgeWorker struct {
// contains filtered or unexported fields
}
ForwardAgentBridgeWorker claims pending clean_agent runtime jobs, asks NodeX to translate the panel payload into a legacy AgentTask, and persists the durable task_id ↔ runtime_job mapping so the agent-task dispatch path can hand it to the target agent. It only touches backend='clean_agent'; nftables_ansible stays on the local ansible executor and gost stays on the synchronous NodeX execute path.
func NewForwardAgentBridgeWorker ¶
func NewForwardAgentBridgeWorker(db *gorm.DB) *ForwardAgentBridgeWorker
func (*ForwardAgentBridgeWorker) RunPendingJobs ¶
func (w *ForwardAgentBridgeWorker) RunPendingJobs(ctx context.Context) error
func (*ForwardAgentBridgeWorker) Start ¶
func (w *ForwardAgentBridgeWorker) Start(ctx context.Context)
type ForwardAnsibleStatsWorker ¶
type ForwardAnsibleStatsWorker struct {
// contains filtered or unexported fields
}
ForwardAnsibleStatsWorker 定期为 nftables_ansible/iptables_ansible 后端的转发采集流量统计。
nftables 路径在 forward hook 的记账链里用两个具名计数器统计每个转发: ct direction original 记为 upload(客户端到目标),ct direction reply 记为 download(目标回到客户端),与 gost 路径的 u/d 同义,再经同一套 traffic_ratio / flow 计费换算。具名计数器在重新下发时保留,只在删除转发时清除。
尚未迁移到 inet 表的转发(以及 iptables 路径)只上报 nat 链计数, 那是每条连接首包的字节数,只能当作 upload,download 为 0。两种快照使用 不同的游标键,迁移时不会互相抵消。
func NewForwardAnsibleStatsWorker ¶
func NewForwardAnsibleStatsWorker(db *gorm.DB) *ForwardAnsibleStatsWorker
func (*ForwardAnsibleStatsWorker) RunOnce ¶
func (w *ForwardAnsibleStatsWorker) RunOnce(ctx context.Context) error
func (*ForwardAnsibleStatsWorker) Start ¶
func (w *ForwardAnsibleStatsWorker) Start(ctx context.Context)
type ForwardCleanAgentAction ¶
type ForwardCleanAgentAction struct {
JobID uint `json:"jobId"`
Action string `json:"action"`
ResourceType string `json:"resourceType"`
ResourceID *uint `json:"resourceId"`
ForwardID *uint `json:"forwardId"`
TunnelID *uint `json:"tunnelId"`
NodeID *uint `json:"nodeId"`
Payload json.RawMessage `json:"payload"`
}
type ForwardCleanAgentHeartbeatInput ¶
type ForwardCleanAgentHeartbeatInput struct {
AgentID uint `json:"agentId"`
Token string `json:"token"`
Version string `json:"version"`
Hostname string `json:"hostname"`
OS string `json:"os"`
Arch string `json:"arch"`
Kernel string `json:"kernel"`
PublicIP string `json:"publicIp"`
PrivateIP string `json:"privateIp"`
Capabilities []string `json:"capabilities"`
Limit int `json:"limit"`
}
type ForwardCleanAgentRegisterInput ¶
type ForwardCleanAgentRegisterInput struct {
Name string `json:"name"`
Token string `json:"token"`
NodeID *uint `json:"nodeId"`
Version string `json:"version"`
Hostname string `json:"hostname"`
OS string `json:"os"`
Arch string `json:"arch"`
Kernel string `json:"kernel"`
PublicIP string `json:"publicIp"`
PrivateIP string `json:"privateIp"`
Capabilities []string `json:"capabilities"`
}
type ForwardCleanAgentReportInput ¶
type ForwardCleanAgentReportInput struct {
AgentID uint `json:"agentId"`
Token string `json:"token"`
JobID uint `json:"jobId"`
Status int `json:"status"`
Success *bool `json:"success"`
Result string `json:"result"`
Error string `json:"error"`
Upload int64 `json:"upload"`
Download int64 `json:"download"`
}
type ForwardCleanAgentService ¶
type ForwardCleanAgentService struct {
// contains filtered or unexported fields
}
func NewForwardCleanAgentService ¶
func NewForwardCleanAgentService(db *gorm.DB) *ForwardCleanAgentService
func (*ForwardCleanAgentService) Heartbeat ¶
func (s *ForwardCleanAgentService) Heartbeat(input ForwardCleanAgentHeartbeatInput) ([]ForwardCleanAgentAction, error)
func (*ForwardCleanAgentService) Register ¶
func (s *ForwardCleanAgentService) Register(input ForwardCleanAgentRegisterInput) (*model.ForwardCleanAgent, error)
Register marks an agent online and binds its token to a node.
A token is bound to the node it was issued for (CreateToken's nodeId) or, for a token an earlier build issued without one, to the node of its first registration that names one. A heartbeat claims the pending jobs of the agent's node, and their payloads carry the node's API token, so a token that could register again under another node could take that node's jobs and credentials. A registration naming another node is refused (ErrForwardCleanAgentNodeMismatch) and changes nothing; one naming no node keeps the binding. Binding to another node takes a new token.
func (*ForwardCleanAgentService) Report ¶
func (s *ForwardCleanAgentService) Report(input ForwardCleanAgentReportInput) error
type ForwardCleanAgentTokenResult ¶
type ForwardCleanAgentTokenResult struct {
Agent *model.ForwardCleanAgent `json:"agent"`
Token string `json:"token"`
}
func CreateCleanAgentTokenTx ¶ added in v4.1.0
func CreateCleanAgentTokenTx(tx *gorm.DB, input ForwardCleanAgentCreateInput) (*ForwardCleanAgentTokenResult, error)
CreateCleanAgentTokenTx is CreateToken in the caller's transaction: the agent row and its split row are written in it, and IssueCleanAgent runs it in the operation's transaction. A token that collides with another (never, in practice) is generated again under a savepoint.
type ForwardFlowResetWorker ¶
type ForwardFlowResetWorker struct {
// contains filtered or unexported fields
}
func NewForwardFlowResetWorker ¶
func NewForwardFlowResetWorker(db *gorm.DB) *ForwardFlowResetWorker
func (*ForwardFlowResetWorker) RunOnce ¶
func (w *ForwardFlowResetWorker) RunOnce(now time.Time) error
func (*ForwardFlowResetWorker) Start ¶
func (w *ForwardFlowResetWorker) Start(ctx context.Context)
type ForwardGostStatsWorker ¶
type ForwardGostStatsWorker struct {
// contains filtered or unexported fields
}
func NewForwardGostStatsWorker ¶
func NewForwardGostStatsWorker(db *gorm.DB) *ForwardGostStatsWorker
func (*ForwardGostStatsWorker) RunOnce ¶
func (w *ForwardGostStatsWorker) RunOnce(ctx context.Context) error
func (*ForwardGostStatsWorker) Start ¶
func (w *ForwardGostStatsWorker) Start(ctx context.Context)
type ForwardLatencyProber ¶
type ForwardLatencyProber struct {
// contains filtered or unexported fields
}
ForwardLatencyProber periodically TCPing-probes forward/tunnel/node targets and stores one pre-aggregated bucket row per (target, time-bucket).
func NewForwardLatencyProber ¶
func NewForwardLatencyProber(db *gorm.DB) *ForwardLatencyProber
func (*ForwardLatencyProber) RunOnce ¶
func (w *ForwardLatencyProber) RunOnce(ctx context.Context) error
RunOnce executes a single probe cycle. Exposed for tests.
func (*ForwardLatencyProber) Start ¶
func (w *ForwardLatencyProber) Start(ctx context.Context)
type ForwardNodeService ¶
type ForwardNodeService struct {
// contains filtered or unexported fields
}
ForwardNodeService 转发节点服务
func NewForwardNodeService ¶
func NewForwardNodeService(db *gorm.DB) *ForwardNodeService
NewForwardNodeService 创建服务
func (*ForwardNodeService) CheckEndpoint ¶ added in v4.1.0
func (s *ForwardNodeService) CheckEndpoint(ctx context.Context, probes DiagnosisProbes, nodeID uint, record bool) (*HealthCheckResult, error)
CheckEndpoint checks one node's endpoint from Control and, with record, writes what it found to the node's row.
func (*ForwardNodeService) CheckEndpoints ¶ added in v4.1.0
func (s *ForwardNodeService) CheckEndpoints(ctx context.Context, probes DiagnosisProbes, nodeIDs []uint, record bool) ([]EndpointCheck, error)
CheckEndpoints checks the nodes' endpoints from Control, at most probes.Concurrency at once, and with record writes each result to its node's row. When ctx ends it returns the checks that completed and ctx's error, and records nothing. Another error is a failure to load the nodes.
func (*ForwardNodeService) Create ¶
func (s *ForwardNodeService) Create(node *model.ForwardNode) error
Create 创建节点. The node's token is written to the split tables in the same transaction (nodesecrets.Sync), as by Update and Delete.
func (*ForwardNodeService) Delete ¶
func (s *ForwardNodeService) Delete(id uint) error
Delete 删除节点 and revoke its agent certificates. The kernel's part, the token's split row and the certificates, is RetireForwardNodeTx, which RetireNode runs too; the node row goes with it in the same transaction.
func (*ForwardNodeService) GenerateAPIToken ¶
func (s *ForwardNodeService) GenerateAPIToken() (string, error)
GenerateAPIToken 生成API Token
func (*ForwardNodeService) GetByID ¶
func (s *ForwardNodeService) GetByID(id uint) (*model.ForwardNode, error)
GetByID 根据ID获取节点
func (*ForwardNodeService) GetByIDForInventoryScope ¶
func (s *ForwardNodeService) GetByIDForInventoryScope(id uint, scope string) (*model.ForwardNode, error)
func (*ForwardNodeService) GetByType ¶
func (s *ForwardNodeService) GetByType(nodeType string) ([]*model.ForwardNode, error)
GetByType 根据类型获取节点列表
func (*ForwardNodeService) HealthCheck ¶
func (s *ForwardNodeService) HealthCheck(ctx context.Context, nodeID uint) (*HealthCheckResult, error)
HealthCheck 健康检查: the forward node check, from Control, recording what it found (CheckEndpoint).
func (*ForwardNodeService) ListByInventoryScope ¶
func (s *ForwardNodeService) ListByInventoryScope(scope, nodeType string, status *int, page, pageSize int) ([]*model.ForwardNode, int64, error)
func (*ForwardNodeService) RecordHealthCheck ¶ added in v4.1.0
func (s *ForwardNodeService) RecordHealthCheck(node *model.ForwardNode, result *HealthCheckResult) error
RecordHealthCheck writes a check's result to the node's row, as the forward node check does: status, last check and latency, and the uptime when the node is online.
func (*ForwardNodeService) Update ¶
func (s *ForwardNodeService) Update(node *model.ForwardNode) error
Update 更新节点. A changed token or a disabled node revokes the node's agent certificates.
type ForwardNodeTraffic ¶ added in v4.1.0
type ForwardNodeTraffic struct {
// Ansible is set for an Ansible machine: it exposes no gost metrics, so
// its panel-side counters are kept.
Ansible bool
// Services are a gost node's services' totals from its metrics
// endpoint.
Services map[string]*gost.ServiceTrafficTotals
// CurrentConn, TotalUpload and TotalDownload are an Ansible machine's
// counters.
CurrentConn int
TotalUpload int64
TotalDownload int64
}
ForwardNodeTraffic is what the statistics sync reads from a forward node.
func CollectForwardNodeTraffic ¶ added in v4.1.0
func CollectForwardNodeTraffic(ctx context.Context, manager *gost.Manager, node *model.ForwardNode, ansible bool) (*ForwardNodeTraffic, error)
CollectForwardNodeTraffic reads node's traffic as the statistics sync does: an Ansible machine's panel-side counters, or every gost service's totals from the node's Prometheus metrics endpoint, through manager.
type ForwardObservabilityService ¶
type ForwardObservabilityService struct {
// contains filtered or unexported fields
}
ForwardObservabilityService serves read-only latency/topology queries backed by the v2_forward_latency_bucket time-series written by ForwardLatencyProber.
func NewForwardObservabilityService ¶
func NewForwardObservabilityService(db *gorm.DB) *ForwardObservabilityService
func (*ForwardObservabilityService) GetMultiIngressLatency ¶
func (s *ForwardObservabilityService) GetMultiIngressLatency(forwardID uint) ([]MultiIngressRow, error)
GetMultiIngressLatency lists, for the forward's exit target, the latest ingress latency of every tunnel reaching the same exit node (incl. the forward's own tunnel).
type ForwardRuleService ¶
type ForwardRuleService struct {
// contains filtered or unexported fields
}
ForwardRuleService handles forward rule persistence and runtime sync.
func NewForwardRuleService ¶
func NewForwardRuleService(db *gorm.DB, nodeService *ForwardNodeService) *ForwardRuleService
NewForwardRuleService preserves the existing constructor shape and uses the default runtime provider.
func NewForwardRuleServiceWithProvider ¶
func NewForwardRuleServiceWithProvider(db *gorm.DB, nodeService *ForwardNodeService, provider ForwardRuntimeProvider) *ForwardRuleService
NewForwardRuleServiceWithProvider allows future runtime backends to be injected explicitly.
func (*ForwardRuleService) ApplyRuntime ¶ added in v4.1.0
func (s *ForwardRuleService) ApplyRuntime(ctx context.Context, rule *model.ForwardRule, action string) error
ApplyRuntime pushes a rule to its relay and exit nodes through the runtime provider (NodeX): create, update or sync apply the row as it is, delete removes it. The legacy routes and the KernelNodeOps forward.legacy_rule executor run it alike; the row is the caller's.
func (*ForwardRuleService) GetByID ¶
func (s *ForwardRuleService) GetByID(id uint) (*model.ForwardRule, error)
GetByID fetches a rule by ID.
func (*ForwardRuleService) GetUserRules ¶
func (s *ForwardRuleService) GetUserRules(userID uint) ([]*model.ForwardRule, error)
GetUserRules fetches rules owned by a user, for the user. Their relay and exit nodes are shown without the nodes' API tokens: a node's token authenticates its agent (verifyForwardNodeToken), so a user who saw it could act as the node.
type ForwardRuntimeOutcome ¶ added in v4.1.0
type ForwardRuntimeOutcome struct {
Backend string
Status int
Message string
Async bool
JobID uint
}
ForwardRuntimeOutcome is what applying a forward on its node reported: the backend in force, the runtime status and message the forward's row records, whether the work was queued (a job backend), and the runtime job row the change recorded.
type ForwardRuntimeProvider ¶
type ForwardRuntimeProvider interface {
CreateForwardRule(ctx context.Context, rule *model.ForwardRule) error
UpdateForwardRule(ctx context.Context, rule *model.ForwardRule) error
DeleteForwardRule(ctx context.Context, rule *model.ForwardRule) error
SyncForwardRule(ctx context.Context, rule *model.ForwardRule) error
}
ForwardRuntimeProvider abstracts the runtime backend used by forward rule sync.
func NewForwardRuntimeProvider ¶
func NewForwardRuntimeProvider(db *gorm.DB) ForwardRuntimeProvider
NewForwardRuntimeProvider returns the default runtime provider.
type GroupMember ¶ added in v4.2.0
type GroupMember struct {
UserID uint `json:"user_id"`
Email string `json:"email"`
Banned int `json:"banned"`
PlanID *uint `json:"plan_id"`
// ExpireAt is when the membership ends (Unix seconds), null for never.
ExpireAt *int64 `json:"expire_at"`
// TransferEnable overrides the user's traffic quota (bytes) while the
// membership lasts, null for no override.
TransferEnable *int64 `json:"transfer_enable"`
// NextRenewPrice is the renewal price in cents, null for none.
NextRenewPrice *int64 `json:"next_renew_price"`
// CreatedAt is when the membership was granted.
CreatedAt time.Time `json:"created_at"`
// Active is whether the membership has not expired.
Active bool `json:"active"`
}
GroupMember is a user the administrator granted the subscription group directly (a v2_user_subscription_group row, what POST /admin/subscription/users/:user_id/groups creates), with the grant's own fields and the user's e-mail, ban flag and plan. It carries no credential: never the subscription token or proxy uuid. The users the group reaches through their plan or their primary group (v2_user.group_id) are not members here, as the stats' user_count does not count them.
type GroupMembersParams ¶ added in v4.2.0
type GroupMembersParams struct {
Page int
PageSize int
// Email, when set, keeps the members whose e-mail contains it; % and _
// match themselves.
Email string
// Status, when set, keeps the members whose membership is "active" (no
// expiry, or one in the future: the stats' enabled users) or "expired".
Status string
}
GroupMembersParams filters and pages a subscription group's members.
type GroupMembersResult ¶ added in v4.2.0
type GroupMembersResult struct {
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
Members []GroupMember `json:"members"`
}
GroupMembersResult is a page of members and how many match in all.
type GroupStats ¶
type GroupStats struct {
GroupID uint `json:"group_id"`
GroupName string `json:"group_name"`
UserCount int64 `json:"user_count"`
TemplateCount int64 `json:"template_count"`
ProtocolCount int64 `json:"protocol_count"`
OnlineNodes int64 `json:"online_nodes"`
TotalTraffic int64 `json:"total_traffic"` // 用户已用流量总和 (bytes)
EnabledUsers int64 `json:"enabled_users"` // 未过期用户数
PlanCount int64 `json:"plan_count"` // 关联套餐数
}
GroupStats 订阅分组统计数据
type HealthCheckResult ¶
type HealthCheckResult struct {
NodeID uint `json:"node_id"`
Status int `json:"status"`
Latency int64 `json:"latency"`
CheckTime time.Time `json:"check_time"`
Error string `json:"error,omitempty"`
}
HealthCheckResult 健康检查结果
type HourlyTraffic ¶
type HourlyTraffic struct {
HourTs int64 `json:"hour_ts"` // 该小时起始的 Unix 秒 (整点)
Traffic int64 `json:"traffic"` // 该小时流量 (字节, 已按倍率计)
}
HourlyTraffic 单个小时的流量统计
type InviteCodeListQuery ¶ added in v4.1.0
InviteCodeListQuery selects a page of invite codes.
type InviteService ¶
type InviteService struct {
// contains filtered or unexported fields
}
InviteService 邀请服务
It keeps the invite configuration (v2_invite_config) in memory and reloads it when the invite settings namespace changed (SettingsGeneration): the affiliate module writes the table it adopted, then the frontend settings through KernelSettings, which bumps the namespace.
func (*InviteService) AddCommission ¶
func (s *InviteService) AddCommission(userID, orderID, fromUserID uint, amount float64, recordType int, remark string) error
AddCommission 添加佣金
func (*InviteService) CalculateCommission ¶
func (s *InviteService) CalculateCommission(orderAmount float64) float64
CalculateCommission 计算佣金
func (*InviteService) GenerateAdminInviteCodes ¶ added in v4.1.0
func (s *InviteService) GenerateAdminInviteCodes(count int, expireDays *int, now time.Time) ([]model.InviteCode, error)
GenerateAdminInviteCodes creates count codes that belong to no user, in one transaction. expireDays nil uses the configured code_expire_days, 0 makes codes that never expire, and a positive value expires them after so many days.
func (*InviteService) GenerateInviteCode ¶
func (s *InviteService) GenerateInviteCode(userID *uint) (*model.InviteCode, error)
GenerateInviteCode 生成邀请码
func (*InviteService) GenerateUserInviteCode ¶ added in v4.1.0
func (s *InviteService) GenerateUserInviteCode(userID uint) (*model.InviteCode, error)
GenerateUserInviteCode generates an invite code a user asked for. As in v2board, a user may hold at most the configured number (code_count, default DefaultInviteCodeLimit) of unused codes; an expired code is not counted, since it can no longer be used. Codes made otherwise (GenerateInviteCode) are not limited.
func (*InviteService) GetCommissionRecords ¶
func (s *InviteService) GetCommissionRecords(userID uint, page, pageSize int) ([]model.CommissionRecord, int64, error)
GetCommissionRecords 获取佣金记录
func (*InviteService) GetConfig ¶
func (s *InviteService) GetConfig() (*model.InviteConfig, error)
GetConfig 获取配置: the copy in memory while the invite settings namespace has not changed since it was loaded.
func (*InviteService) GetInviteStats ¶
func (s *InviteService) GetInviteStats(userID uint) (map[string]any, error)
GetInviteStats 获取邀请统计
func (*InviteService) GetUserInviteCodes ¶
func (s *InviteService) GetUserInviteCodes(userID uint) ([]model.InviteCode, error)
GetUserInviteCodes 获取用户邀请码
func (*InviteService) GetWithdrawRecords ¶
func (s *InviteService) GetWithdrawRecords(userID uint, page, pageSize int) ([]model.CommissionWithdraw, int64, error)
GetWithdrawRecords 获取提现记录
func (*InviteService) ListInviteCodes ¶ added in v4.1.0
func (s *InviteService) ListInviteCodes(query InviteCodeListQuery, now time.Time) ([]model.InviteCode, int64, error)
ListInviteCodes returns a page of every invite code, newest first, and the number of codes the filter matches. An unused code past its expiry counts as expired, not unused.
func (*InviteService) ProcessWithdraw ¶ added in v4.1.0
func (s *InviteService) ProcessWithdraw(withdraw *model.CommissionWithdraw, status int, remark string, now time.Time) error
ProcessWithdraw approves (status 1) or rejects (status 2) a withdrawal that is still pending, as of now. The decision applies only while the withdrawal is pending, so of two concurrent decisions one fails with ErrWithdrawalProcessed. A rejection returns the amount to the commission balance in the same transaction, once (WithdrawRefundRequestID); if that fails, nothing changes. A withdrawal whose user no longer exists has no one to refund and is rejected all the same. withdraw is updated on success.
func (*InviteService) RequestWithdraw ¶
func (s *InviteService) RequestWithdraw(userID uint, amount float64, method, account, name string) (*model.CommissionWithdraw, error)
RequestWithdraw 申请提现. The amount is a whole number in the commission balance's unit (cents) and at least the configured minimum, read for each request so an administrator's change applies at once. The withdrawal and its debit (WithdrawDebitRequestID) are one transaction, and the debit is taken under the subscriber's row lock and refused below zero (subscriber.AdjustBalanceTx), so concurrent requests cannot overdraw.
func (*InviteService) RevokeInviteCode ¶ added in v4.1.0
func (s *InviteService) RevokeInviteCode(id uint) error
RevokeInviteCode deletes an unused code, whoever it belongs to, so no registration can consume it. A used code is refused: it records who registered with it. The delete names the unused state, so a registration that consumes the code first wins.
func (*InviteService) SaveConfig ¶ added in v4.1.0
func (s *InviteService) SaveConfig(cfg *model.InviteConfig) error
SaveConfig saves cfg and makes it the configuration in memory; every other copy reloads.
func (*InviteService) SetConfig ¶
func (s *InviteService) SetConfig(cfg *model.InviteConfig)
SetConfig 设置配置: cfg becomes the configuration in memory, and every other copy reloads.
type KernelOperationStatus ¶
type KernelOperationStatus struct {
ID string `json:"id"`
NodeID *uint `json:"node_id,omitempty"`
PluginID string `json:"plugin_id"`
TargetVersion string `json:"target_version"`
TopologyDeploymentID *uint `json:"topology_deployment_id,omitempty"`
TopologyStepID *uint `json:"topology_step_id,omitempty"`
TopologyRevision int64 `json:"topology_revision,omitempty"`
Kind string `json:"kind"`
OperationChain string `json:"operation_chain,omitempty"`
Revision int64 `json:"revision"`
ConfigHash string `json:"config_hash,omitempty"`
State string `json:"state"`
DeadlineAt *time.Time `json:"deadline_at,omitempty"`
DispatchedAt *time.Time `json:"dispatched_at,omitempty"`
AcknowledgedAt *time.Time `json:"acknowledged_at,omitempty"`
ObservedAt *time.Time `json:"observed_at,omitempty"`
CancelAt *time.Time `json:"cancel_at,omitempty"`
Attempt int `json:"attempt"`
HasResult bool `json:"has_result"`
HasError bool `json:"has_error"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
KernelOperationStatus is the public, non-secret projection of a durable operation. ConfigJSON, ResultJSON, session identity, and raw Agent errors intentionally stay inside the kernel persistence boundary.
func PublicKernelOperation ¶
func PublicKernelOperation(operation model.KernelOperation) KernelOperationStatus
type LatencyPoint ¶
type LatencyTrend ¶
type LegacyForwardAnsibleCleaner ¶ added in v4.2.0
type LegacyForwardAnsibleCleaner struct {
DB *gorm.DB
// Playbook overrides LegacyForwardCleanupPlaybook.
Playbook string
// Run replaces running ansible-playbook (tests).
Run func(ctx context.Context, command string, args []string, workdir string, env map[string]string) (string, error)
// Timeout bounds one host's run; 5 minutes when zero.
Timeout time.Duration
}
LegacyForwardAnsibleCleaner runs the cleanup playbook on a host of the Ansible fallback: an Ansible machine, or the execution node of a flux forward on an Ansible backend.
func (*LegacyForwardAnsibleCleaner) CleanNode ¶ added in v4.2.0
func (c *LegacyForwardAnsibleCleaner) CleanNode(ctx context.Context, node forwardlegacy.NodeInfo) forwardlegacy.PathResult
CleanNode runs the cleanup playbook limited to the node's host.
type LegacyForwardNodeXCleaner ¶ added in v4.2.0
type LegacyForwardNodeXCleaner struct {
DB *gorm.DB
// HTTPClient replaces the NodeX client's HTTP client (tests).
HTTPClient interface {
Do(*http.Request) (*http.Response, error)
}
}
LegacyForwardNodeXCleaner deletes a node's flux gost services through NodeX. NodeX has no listing call: a delete is idempotent, so running the check again is the re-check.
func (*LegacyForwardNodeXCleaner) CleanNode ¶ added in v4.2.0
func (c *LegacyForwardNodeXCleaner) CleanNode(ctx context.Context, node forwardlegacy.NodeInfo) forwardlegacy.PathResult
CleanNode deletes, through NodeX, every flux forward whose tunnel enters at the node on the gost backend, and every legacy rule relayed or exited by the node.
type LoadBalancerService ¶
type LoadBalancerService struct {
// contains filtered or unexported fields
}
LoadBalancerService 负载均衡服务
func NewLoadBalancerService ¶
func NewLoadBalancerService(db *gorm.DB) *LoadBalancerService
NewLoadBalancerService 创建服务
func (*LoadBalancerService) Create ¶
func (s *LoadBalancerService) Create(lb *model.LoadBalancer) error
Create 创建负载均衡器
func (*LoadBalancerService) Delete ¶
func (s *LoadBalancerService) Delete(id uint) error
Delete 删除负载均衡器
func (*LoadBalancerService) GetByID ¶
func (s *LoadBalancerService) GetByID(id uint) (*model.LoadBalancer, error)
GetByID 获取负载均衡器
func (*LoadBalancerService) GetStats ¶
func (s *LoadBalancerService) GetStats(lbID uint) (map[string]any, error)
GetStats 获取负载均衡统计
func (*LoadBalancerService) List ¶
func (s *LoadBalancerService) List(groupID uint) ([]model.LoadBalancer, error)
List 获取负载均衡器列表
func (*LoadBalancerService) RunHealthCheck ¶
func (s *LoadBalancerService) RunHealthCheck(lbID uint) error
RunHealthCheck 执行健康检查
func (*LoadBalancerService) SelectNode ¶
func (s *LoadBalancerService) SelectNode(lbID uint) (*model.ForwardNode, error)
SelectNode 选择最佳节点
func (*LoadBalancerService) Update ¶
func (s *LoadBalancerService) Update(lb *model.LoadBalancer) error
Update 更新负载均衡器
type LoginRateLimitOptions ¶
type LoginRateLimitOptions struct {
Enabled bool
MaxAttempts int
Window time.Duration
Lockout time.Duration
CleanupAfter time.Duration
}
func ResolveLoginRateLimitOptions ¶
func ResolveLoginRateLimitOptions(cfg *config.Config) LoginRateLimitOptions
func ResolveRegisterRateLimitOptions ¶
func ResolveRegisterRateLimitOptions(cfg *config.Config) LoginRateLimitOptions
type LoginRateLimiter ¶
type LoginRateLimiter struct {
// contains filtered or unexported fields
}
func GetLoginRateLimiter ¶
func GetLoginRateLimiter() *LoginRateLimiter
func GetSubscriptionResetLimiter ¶ added in v4.1.0
func GetSubscriptionResetLimiter() *LoginRateLimiter
GetSubscriptionResetLimiter returns the limiter of users' subscription resets, kept apart from the login limiter so that neither's cleanup forgets the other's keys early.
func NewLoginRateLimiter ¶
func NewLoginRateLimiter() *LoginRateLimiter
func (*LoginRateLimiter) Check ¶
func (l *LoginRateLimiter) Check(key string, options LoginRateLimitOptions) (bool, time.Duration)
func (*LoginRateLimiter) RecordFailure ¶
func (l *LoginRateLimiter) RecordFailure(key string, options LoginRateLimitOptions)
func (*LoginRateLimiter) RecordSuccess ¶
func (l *LoginRateLimiter) RecordSuccess(key string)
type MFAService ¶
type MFAService struct {
// contains filtered or unexported fields
}
MFAService MFA服务
func NewMFAService ¶
func NewMFAService(db *gorm.DB, config *model.MFAConfig) *MFAService
NewMFAService 创建服务
func (*MFAService) CheckBruteForce ¶
func (s *MFAService) CheckBruteForce(userID uint, maxAttempts int, window time.Duration) (bool, error)
CheckBruteForce 检查暴力破解
Implemented but not yet wired into the MFA verification flow; see TODO.md ("Implemented but not wired").
func (*MFAService) DisableMFA ¶
func (s *MFAService) DisableMFA(userID uint, password string) error
DisableMFA 禁用MFA
func (*MFAService) EnableTOTP ¶
func (s *MFAService) EnableTOTP(userID uint, code string) error
EnableTOTP 启用TOTP
func (*MFAService) GetRemainingBackupCodes ¶
func (s *MFAService) GetRemainingBackupCodes(userID uint) (int, error)
GetRemainingBackupCodes 获取剩余备用码数量
func (*MFAService) GetUserMFA ¶
func (s *MFAService) GetUserMFA(userID uint) (*model.UserMFA, error)
GetUserMFA 获取用户MFA配置
func (*MFAService) IsEnforcedForUser ¶
func (s *MFAService) IsEnforcedForUser(user *model.User) bool
IsEnforcedForUser 检查是否对用户强制MFA
func (*MFAService) RecordLoginAttempt ¶
func (s *MFAService) RecordLoginAttempt(userID uint, ip, userAgent string, success bool, method string) error
RecordLoginAttempt 记录登录尝试
func (*MFAService) RegenerateBackupCodes ¶
func (s *MFAService) RegenerateBackupCodes(userID uint) ([]string, error)
RegenerateBackupCodes 重新生成备用码
func (*MFAService) SetConfig ¶
func (s *MFAService) SetConfig(config *model.MFAConfig)
SetConfig updates MFA runtime config without recreating service.
func (*MFAService) SetupTOTP ¶
func (s *MFAService) SetupTOTP(userID uint, email string) (*TOTPSetup, error)
SetupTOTP 设置TOTP
func (*MFAService) Verify ¶
func (s *MFAService) Verify(userID uint, code, method string) (bool, error)
Verify 验证MFA代码
func (*MFAService) VerifyBackupCode ¶
VerifyBackupCode 验证备用码
func (*MFAService) VerifyTOTP ¶
func (s *MFAService) VerifyTOTP(secret, code string) bool
VerifyTOTP 验证TOTP代码
type MultiIngressRow ¶
type MultiIngressRow struct {
TunnelID uint `json:"tunnelId"`
TunnelName string `json:"tunnelName"`
IngressNodeID uint `json:"ingressNodeId"`
IngressLabel string `json:"ingressLabel"`
IngressIP string `json:"ingressIp"`
AvgRTT float64 `json:"avgRtt"`
Loss float64 `json:"loss"`
BucketAt int64 `json:"bucketAt"`
Online bool `json:"online"`
}
type NodeListParams ¶
type NodeListResult ¶
type NodeLogInput ¶
type NodeLogListParams ¶
type NodeLogListResult ¶
type NodeLogService ¶
type NodeLogService struct {
// contains filtered or unexported fields
}
func NewNodeLogService ¶
func NewNodeLogService() *NodeLogService
func (*NodeLogService) GetLogs ¶
func (s *NodeLogService) GetLogs(params NodeLogListParams) (*NodeLogListResult, error)
func (*NodeLogService) RecordAgentLogBatch ¶ added in v4.1.0
func (s *NodeLogService) RecordAgentLogBatch(nodeKind string, nodeID uint, batchID string, inputs []NodeLogInput) (bool, error)
RecordAgentLogBatch records a LogBatch from the Agent Control stream (reports.v1) as RecordLogs records the legacy NodeLogService batch, once per node and batch id: the batch record (internal/agentreports) is claimed in the transaction that inserts the rows. It reports whether this call recorded the batch; false means a committed transaction recorded it before. gorm.ErrRecordNotFound means the node does not exist.
func (*NodeLogService) RecordAgentMaintenanceEvent ¶ added in v4.2.0
func (s *NodeLogService) RecordAgentMaintenanceEvent(nodeKind string, nodeID uint, event agentcontrol.MaintenanceEvent) (bool, error)
RecordAgentMaintenanceEvent records one maintenance event of the Agent Control stream (maintenance.v1) once per node and event id: a v2_node_log row of source "maintenance" whose fields_json is the event, inserted in the transaction that claims the event's record (internal/agentreports, kind maintenance). It reports whether this call recorded the event; false means a committed transaction recorded it before. gorm.ErrRecordNotFound means the node does not exist.
func (*NodeLogService) RecordLogs ¶
func (s *NodeLogService) RecordLogs(nodeID uint, inputs []NodeLogInput) error
func (*NodeLogService) RecordLogsTx ¶ added in v4.1.0
func (s *NodeLogService) RecordLogsTx(tx *gorm.DB, nodeID uint, inputs []NodeLogInput) error
RecordLogsTx is RecordLogs inside tx.
type NodeMonthlyResetWorker ¶
type NodeMonthlyResetWorker struct {
// contains filtered or unexported fields
}
NodeMonthlyResetWorker 按每个节点自己的 MonthlyResetDay 把 monthly_upload/ monthly_download 清零, 用于月流量限额的周期性重置(仅统计层面, 不做任何 自动禁用/限速动作)。
func NewNodeMonthlyResetWorker ¶
func NewNodeMonthlyResetWorker(db *gorm.DB) *NodeMonthlyResetWorker
func (*NodeMonthlyResetWorker) RunOnce ¶
func (w *NodeMonthlyResetWorker) RunOnce(now time.Time) error
func (*NodeMonthlyResetWorker) Start ¶
func (w *NodeMonthlyResetWorker) Start(ctx context.Context)
type NodePluginObservedSnapshot ¶
type NodePluginObservedSnapshot struct {
PluginID string
Version string
DesiredRevision uint64
ObservedRevision uint64
ConfigHash string
Health string
RulesetSHA256 string
ObservedAt time.Time
RuleCounters []NodePluginRuleCounter
}
NodePluginObservedSnapshot is the bounded data the authenticated Agent may contribute on its heartbeat. It deliberately has no raw plugin payload or error text: those would make the generic observed-state API a secret leak.
type NodePluginRuleCounter ¶
type NodePluginRuleCounter struct {
RuleID string `json:"rule_id"`
Packets uint64 `json:"packets"`
Bytes uint64 `json:"bytes"`
}
NodePluginRuleCounter is the kernel-neutral form of one plugin-owned counter. The kernel stores it as opaque, bounded data and does not infer quota or billing semantics from it.
type NodeSecretFinding ¶ added in v4.1.0
type NodeSecretFinding struct {
NodeID uint `json:"node_id"`
// ProtocolID is zero for a node's raw configuration.
ProtocolID uint `json:"protocol_id,omitempty"`
// Type is the protocol's type, or raw_config.
Type string `json:"type"`
Enabled bool `json:"enabled"`
Column string `json:"column"`
// Field is the secret's JSON pointer; empty for a whole column.
Field string `json:"field"`
Reason string `json:"reason"`
}
NodeSecretFinding names one secret that fails validation: where it is and why, never its value.
func ValidateProtocolSecrets ¶ added in v4.1.0
func ValidateProtocolSecrets(protocol *model.NodeProtocol) []NodeSecretFinding
ValidateProtocolSecrets checks the secrets of one node protocol, as the configuration builder uses them: no secret position holds the placeholder or a tombstone, and the keys the node parses (a WireGuard entry's server key pair, a Reality private key, a Shadowsocks 2022 server key) are well formed.
func ValidateRawConfigSecrets ¶ added in v4.1.0
func ValidateRawConfigSecrets(node *model.Node) []NodeSecretFinding
ValidateRawConfigSecrets checks the secrets of a node's raw configuration: no secret position holds the placeholder or a tombstone. The kernel already refuses a WireGuard raw configuration that fails its runtime validation.
type NodeSecretValidation ¶ added in v4.1.0
type NodeSecretValidation struct {
// Protocols and RawConfigs count the rows checked.
Protocols int64 `json:"protocols"`
RawConfigs int64 `json:"raw_configs"`
Findings []NodeSecretFinding `json:"findings"`
// Excluded is always zero: validation reports and excludes nothing
// (D7).
Excluded int `json:"excluded"`
}
NodeSecretValidation is the outcome of ScanNodeSecrets.
func ScanNodeSecrets ¶ added in v4.1.0
ScanNodeSecrets checks every node protocol and every node raw configuration as the configuration builder would use them (their secrets read through the node credential split, in the table's phase), and reports the findings. It changes nothing.
type NodeService ¶
type NodeService struct {
// contains filtered or unexported fields
}
NodeService 节点服务
func (*NodeService) AccumulateTrafficOnly ¶
func (s *NodeService) AccumulateTrafficOnly(nodeID uint, upload, download int64) error
AccumulateTrafficOnly 仅把流量累加到节点自身及其父节点链,不更新心跳指标。
func (*NodeService) AssignProtocolsToGroup ¶
func (s *NodeService) AssignProtocolsToGroup(groupID uint, protocolIDs []uint) error
AssignProtocolsToGroup 为分组分配节点协议
func (*NodeService) BuildUniProxyConfig ¶ added in v4.1.0
func (s *NodeService) BuildUniProxyConfig(nodeID uint, preferredType string) (map[string]any, error)
BuildUniProxyConfig is BuildUniProxyNodeConfig over the service's database.
func (*NodeService) CreateNode ¶
func (s *NodeService) CreateNode(node *model.Node) error
CreateNode 创建节点 (手动添加), its own columns only.
Node and node protocol writes take the model or the map an administrator's body was bound to. GORM saves the associations of a model it creates: a node body's "protocols" moved other nodes' protocols to the new node, and the nodes and subscription groups nested in them were created, those nodes without an API key. A body's id chose the new row's id. Protocols have their own routes and are never saved from a node body.
func (*NodeService) CreateProtocol ¶
func (s *NodeService) CreateProtocol(protocol *model.NodeProtocol) error
CreateProtocol 创建协议, its own columns only (see CreateNode): a protocol body's "node" created a node without an API key and moved the protocol to it, and its "subscription_groups" were created and linked. Linking protocols to groups has its own route. A secret sent as NodeSecretPlaceholder is stored empty, since nothing is stored yet.
func (*NodeService) DeleteAuthKey ¶
func (s *NodeService) DeleteAuthKey(id uint) error
DeleteAuthKey 删除授权密钥, as RevokeRegistrationKey does.
func (*NodeService) DeleteNode ¶
func (s *NodeService) DeleteNode(id uint) error
DeleteNode 删除节点
The kernel's part, the protocols with their peers, links and secrets, the credentials and the agent certificates, is RetireProxyNodeTx, which RetireNode runs too; the node row goes with it in the same transaction.
func (*NodeService) DeleteProtocol ¶
func (s *NodeService) DeleteProtocol(id uint) error
DeleteProtocol 删除协议. The kernel's part, the peers, links and secrets, is RetireProtocolTx, which RetireProtocol runs too; the protocol row goes with it in the same transaction.
func (*NodeService) GenerateAuthKey ¶
func (s *NodeService) GenerateAuthKey(name string, expireDays int) (*model.AuthorizedKey, string, error)
GenerateAuthKey 生成授权密钥, as IssueRegistrationKey does.
func (*NodeService) GetAllAvailableProtocols ¶
func (s *NodeService) GetAllAvailableProtocols() ([]model.NodeProtocol, error)
GetAllAvailableProtocols 获取所有可显示在订阅中的协议
func (*NodeService) GetAuthKeys ¶
func (s *NodeService) GetAuthKeys() ([]model.AuthorizedKey, error)
GetAuthKeys 获取授权密钥列表
func (*NodeService) GetNode ¶
func (s *NodeService) GetNode(id uint) (*model.Node, error)
GetNode 获取节点详情
func (*NodeService) GetNodeByAPIKey ¶
func (s *NodeService) GetNodeByAPIKey(apiKey string) (*model.Node, error)
GetNodeByAPIKey 通过API Key获取节点 by its stored hash, for the gRPC node listener and the Agent Control stream. The lookup goes through the node credential split, which applies the table's phase and never matches a tombstone or the placeholder.
func (*NodeService) GetNodeStats ¶
func (s *NodeService) GetNodeStats() (map[string]any, error)
GetNodeStats 获取节点统计
func (*NodeService) GetNodes ¶
func (s *NodeService) GetNodes(params NodeListParams) (*NodeListResult, error)
GetNodes 获取节点列表
func (*NodeService) GetProtocol ¶
func (s *NodeService) GetProtocol(id uint) (*model.NodeProtocol, error)
GetProtocol 获取协议详情
func (*NodeService) GetProtocols ¶
func (s *NodeService) GetProtocols(nodeID uint) ([]model.NodeProtocol, error)
GetProtocols 获取节点的协议列表
func (*NodeService) GetProtocolsByGroup ¶
func (s *NodeService) GetProtocolsByGroup(groupID uint) ([]model.NodeProtocol, error)
GetProtocolsByGroup 获取关联到特定分组的协议列表
func (*NodeService) Heartbeat ¶
func (s *NodeService) Heartbeat(nodeID uint, req *model.NodeHeartbeatRequest) error
Heartbeat 节点心跳
func (*NodeService) LatestPackageReport ¶ added in v4.2.0
func (s *NodeService) LatestPackageReport(nodeKind string, nodeID uint, pluginID, kind string, now time.Time) (PackageReport, error)
LatestPackageReport returns the latest report of a node, plugin and kind, or gorm.ErrRecordNotFound.
func (*NodeService) NodeCredentials ¶ added in v4.1.0
func (s *NodeService) NodeCredentials(node *model.Node) (apiKey, secret string)
NodeCredentials answers node's API key and shared secret, where the kernel shows them to an administrator, read through the node credential split.
func (*NodeService) PrepareNodeRawConfig ¶ added in v4.1.0
func (s *NodeService) PrepareNodeRawConfig(node *model.Node)
PrepareNodeRawConfig reads the secrets of node's raw configuration through the node credential split, in place, before UniProxy builds the node's configuration from it, and reports a secret that fails validation (report-only, D7).
func (*NodeService) RecordAgentNodeStatus ¶ added in v4.1.0
func (s *NodeService) RecordAgentNodeStatus(nodeID uint, status AgentNodeStatus) error
RecordAgentNodeStatus writes what the legacy ReportStatus heartbeat and the runtime-health report write together: the system metrics, the heartbeat (last_check_at and the status, which never re-enables a disabled node) and the runtime health. online_users is not here: the stream's TrafficReport.online keeps it. A node that does not exist is gorm.ErrRecordNotFound.
func (*NodeService) RecordNodePluginObservedStates ¶
func (s *NodeService) RecordNodePluginObservedStates(nodeID uint, snapshots []NodePluginObservedSnapshot, receivedAt time.Time) (int, error)
RecordNodePluginObservedStates stores trusted, monotonic plugin runtime snapshots from an authenticated node. A malformed or unauthorized snapshot is rejected independently so one bad plugin cannot suppress another plugin's heartbeat evidence.
func (*NodeService) RecordPackageReport ¶ added in v4.2.0
func (s *NodeService) RecordPackageReport(input PackageReportInput, receivedAt time.Time) (bool, error)
RecordPackageReport authorizes, sanitizes and stores a package report as the latest of its node, plugin and kind. It returns true when the report was stored and false when a newer one was stored before (the report is dropped). A *PackageReportRefusedError refuses the report for good; any other error means the kernel could not record it now.
func (*NodeService) RecordPluginTelemetry ¶
func (s *NodeService) RecordPluginTelemetry(nodeID uint, heartbeatMetrics map[string]float64, receivedAt time.Time) (int, error)
RecordPluginTelemetry persists only metrics from enabled assignments on the authenticated node. Non-plugin heartbeat metrics remain kernel-owned and are intentionally excluded from this plugin state table.
func (*NodeService) RegisterNode ¶
func (s *NodeService) RegisterNode(req *model.NodeRegisterRequest, clientIP string) (*model.NodeRegisterResponse, error)
RegisterNode 节点自动注册
func (*NodeService) SyncProtocolToNode ¶
func (s *NodeService) SyncProtocolToNode(nodeID uint) error
SyncProtocolToNode 同步协议配置到节点
func (*NodeService) UpdateLastCheckAt ¶
func (s *NodeService) UpdateLastCheckAt(nodeID uint) error
UpdateLastCheckAt 更新节点最后检查时间 (用于 UniProxy 接口)
func (*NodeService) UpdateNode ¶
func (s *NodeService) UpdateNode(id uint, updates map[string]any) error
UpdateNode 更新节点. The node's id and credentials are never updated, and a new parent is checked whatever spelling names it (see columnUpdates). A raw configuration secret sent as NodeSecretPlaceholder keeps its stored value.
func (*NodeService) UpdateOnlineUsers ¶ added in v4.1.0
func (s *NodeService) UpdateOnlineUsers(nodeID uint, count int) error
UpdateOnlineUsers records how many users a node's last online report listed, as the legacy status heartbeat records online_users.
func (*NodeService) UpdateProtocol ¶
func (s *NodeService) UpdateProtocol(id uint, updates map[string]any) error
UpdateProtocol 更新协议. The protocol's id and node are never updated, and the update is checked with the values it writes, whatever spelling names them (see columnUpdates). A secret sent as NodeSecretPlaceholder, as the administrator's answers show it, keeps its stored value.
func (*NodeService) UpdateRuntimeHealth ¶
func (s *NodeService) UpdateRuntimeHealth(nodeID uint, healthy bool, message string) error
UpdateRuntimeHealth records the health of a node's managed runtime process. It deliberately does not change last_check_at: the node can be reachable while its relay process is unhealthy, and those are different signals.
type NodeTrafficPoint ¶ added in v4.2.0
NodeTrafficPoint is one bucket of a node's traffic series: the bytes the node's users moved through it, with the node's traffic rate applied (the bytes the panel meters, as /admin/traffic/hourly and the statistics tables count them).
type NodeTrafficSeries ¶ added in v4.2.0
type NodeTrafficSeries struct {
NodeID uint
Granularity string
Since time.Time
Until time.Time
Points []NodeTrafficPoint
}
NodeTrafficSeries is a node's traffic over [Since, Until) in buckets of Granularity, ascending, with the buckets without traffic as zeros.
type NotificationService ¶
type NotificationService struct {
// contains filtered or unexported fields
}
NotificationService 通知服务
func NewNotificationService ¶
func NewNotificationService(db *gorm.DB, cfg *config.Config) *NotificationService
NewNotificationService 创建服务
func (*NotificationService) Broadcast ¶
func (s *NotificationService) Broadcast(title, content string) error
Broadcast 广播通知 (所有用户)
func (*NotificationService) Drain ¶
func (s *NotificationService) Drain()
Drain waits for all asynchronous notifications registered before the call. The registration mutex prevents WaitGroup.Add from racing with Wait.
func (*NotificationService) NotifyAdministrators ¶ added in v4.2.0
func (s *NotificationService) NotifyAdministrators(event, title, content string, data map[string]any) error
NotifyAdministrators sends one notification to every administrator who is not banned: always as an in-app entry in the notification log, by e-mail when the e-mail settings are configured (SetEmailConfig), and by Telegram when the administrator bound an account. It is the delivery of the kernel alert monitor's digests (internal/kernelalerts). The title is cut to the log's width.
func (*NotificationService) NotifyNodeOffline ¶
func (s *NotificationService) NotifyNodeOffline(node *model.Node) error
NotifyNodeOffline 节点离线通知 (管理员)
func (*NotificationService) NotifyOrderPaid ¶
NotifyOrderPaid 订单支付成功通知
func (*NotificationService) NotifyTicketReply ¶
func (s *NotificationService) NotifyTicketReply(ticket *model.Ticket, replyBy string) error
NotifyTicketReply 工单回复通知
func (*NotificationService) NotifyTrafficLow ¶
func (s *NotificationService) NotifyTrafficLow(user *model.User, percentLeft float64) error
NotifyTrafficLow 流量不足通知
func (*NotificationService) NotifyUserExpire ¶
func (s *NotificationService) NotifyUserExpire(user *model.User, daysLeft int) error
NotifyUserExpire 用户到期通知
func (*NotificationService) Send ¶
func (s *NotificationService) Send(userID *uint, notifyType, event, title, content string, data map[string]any) error
Send 发送通知
func (*NotificationService) SendEmail ¶
func (s *NotificationService) SendEmail(to, subject, body string) error
SendEmail 发送邮件
func (*NotificationService) SetEmailConfig ¶
func (s *NotificationService) SetEmailConfig(cfg *model.EmailConfig)
SetEmailConfig 设置邮件配置
type OperationLogInput ¶
type OperationLogInput struct {
UserID *uint
Username string
Action string
Module string
TargetType string
TargetID *uint
Content string
IP string
UserAgent string
Status int
}
func BackupConfigAuditInput ¶ added in v4.1.0
func BackupConfigAuditInput(actor SettingsAuditActor, action string, cfg *model.BackupConfig, preservedSensitiveFields []string) *OperationLogInput
BackupConfigAuditInput is the audit entry of a backup configuration change: every field but the S3 keys, whether each S3 key has a value, and which of them were kept.
func SystemConfigAuditInput ¶ added in v4.1.0
func SystemConfigAuditInput(actor SettingsAuditActor, action string, cfg *model.SystemConfig, preserveExisting bool) *OperationLogInput
SystemConfigAuditInput is the audit entry of a system configuration change: which key, its group and type, whether it is a secret and has a value, and whether the stored secret was kept. For a value with masked fields (the SMTP password of the e-mail configuration) it also names them and those that hold a value. It never holds the value.
type OperationLogService ¶
type OperationLogService struct {
// contains filtered or unexported fields
}
func NewOperationLogService ¶
func NewOperationLogService(db *gorm.DB) *OperationLogService
func (*OperationLogService) Record ¶
func (s *OperationLogService) Record(input *OperationLogInput) error
type OrderBuyerRef ¶ added in v4.1.0
OrderBuyerRef names an order's buyer in an administrator's order list and detail answers.
type OrderListParams ¶
type OrderListParams struct {
Page int
PageSize int
UserID *uint
Status *int
Type *int
TradeNo string
Email string
// OrderBy is an ORDER BY clause from v2compat.ParseListSort over
// OrderSortColumns, never request text; empty keeps the default order.
OrderBy string
}
OrderListParams 订单列表查询参数
type OrderListResult ¶
OrderListResult 订单列表结果
type OrderPaymentReconciler ¶ added in v4.1.0
type OrderPaymentReconciler struct {
// Grace, Batch and MaxBatches default to the package constants.
Grace time.Duration
Batch int
MaxBatches int
// contains filtered or unexported fields
}
OrderPaymentReconciler completes the orders of paid payment records that are still pending (docs/architecture/order-service.md): the payment module records a paid callback, then asks KernelOrder to complete the order; if that second step fails and the provider never delivers again, the record stays paid and the order pending. The reconciler runs the same second step, CompleteOrderPaymentTx with request id payment:<trade_no>, so it re-checks the record against the order and applies it once; a record that fails the checks is refused and logged, and the order is left unchanged.
func NewOrderPaymentReconciler ¶ added in v4.1.0
func NewOrderPaymentReconciler(db *gorm.DB) *OrderPaymentReconciler
NewOrderPaymentReconciler returns a reconciler on db, or on the kernel's database when db is nil.
func (*OrderPaymentReconciler) RunOnce ¶ added in v4.1.0
func (r *OrderPaymentReconciler) RunOnce(ctx context.Context, now time.Time) (OrderPaymentReconciliation, error)
RunOnce applies the candidate records as of now, in batches, each record in its own transaction. It stops early when ctx is cancelled. Running it again, or in two processes at once, changes nothing more: the record's row lock and its request id apply it once.
type OrderPaymentReconciliation ¶ added in v4.1.0
type OrderPaymentReconciliation struct {
// Examined is the number of candidate records the run read.
Examined int
// Completed, Paid and Refused count the outcomes the run recorded.
Completed int
Paid int
Refused int
// Unchanged counts records another caller applied first (a callback's
// repeat, or a reconciler in another process).
Unchanged int
// Failed counts records whose completion failed; nothing was recorded,
// so a later run tries again.
Failed int
}
OrderPaymentReconciliation counts what one run did.
type OrderPaymentResult ¶ added in v4.1.0
type OrderPaymentResult struct {
// Applied is false when the trade number was applied before; the other
// fields then describe that first application.
Applied bool `json:"-"`
OrderID uint64 `json:"order_id"`
Outcome string `json:"outcome"`
// Reason says why a refused record does not pay its order.
Reason string `json:"reason,omitempty"`
}
OrderPaymentResult is the outcome of CompleteOrderPaymentTx, as the request ledger records it.
func CompleteOrderPaymentTx ¶ added in v4.1.0
func CompleteOrderPaymentTx(tx *gorm.DB, tradeNo string, orderID uint64, now time.Time) (OrderPaymentResult, error)
CompleteOrderPaymentTx applies the paid payment record tradeNo to the order it names, orderID, in tx: it re-checks that the record pays the order, marks the order paid and completes it (grants its plan with request id "order:<id>", in a savepoint). The outcome is recorded in the request ledger under OrderPaymentRequestID, so a trade number is applied once and a repeat answers the first outcome.
The kernel's payment callbacks call it in the transaction that marks the record paid; KernelOrder.CompleteOrderPayment calls it after the payment module committed the record. It locks the record, then the order.
type OrderPlanRef ¶ added in v4.1.0
OrderPlanRef names an order's plan in the order list and detail answers.
type OrderService ¶
type OrderService struct {
// contains filtered or unexported fields
}
OrderService 订单服务
func (*OrderService) Complete ¶
func (s *OrderService) Complete(orderID uint) error
Complete 完成订单 (支付成功后处理)
func (*OrderService) Create ¶
func (s *OrderService) Create(params CreateOrderParams) (*model.Order, error)
Create 创建订单
func (*OrderService) GetAdminView ¶ added in v4.1.0
func (s *OrderService) GetAdminView(id uint) (*OrderView, error)
GetAdminView is an administrator's order detail: the order with its plan and buyer.
func (*OrderService) GetByID ¶
func (s *OrderService) GetByID(id uint) (*model.Order, error)
GetByID 根据ID获取订单, without its plan or buyer.
func (*OrderService) GetList ¶
func (s *OrderService) GetList(params OrderListParams) (*OrderListResult, error)
GetList is an administrator's order list, newest first, each order with its buyer.
func (*OrderService) GetStats ¶
func (s *OrderService) GetStats() (map[string]any, error)
GetStats 获取订单统计
func (*OrderService) GetUserOrders ¶
func (s *OrderService) GetUserOrders(userID uint, page, pageSize int) (*OrderListResult, error)
GetUserOrders is a user's own orders, newest first, each with its plan and without the buyer. A user id of zero names no one and has no orders.
func (*OrderService) GetUserView ¶ added in v4.1.0
func (s *OrderService) GetUserView(userID, id uint) (*OrderView, error)
GetUserView is a user's order detail: the order, if it is the user's, with its plan. Another user's order is ErrOrderNotFound, as an unknown one.
func (*OrderService) UpdateStatus ¶
func (s *OrderService) UpdateStatus(orderID uint, status int) error
UpdateStatus 更新订单状态
type OrderView ¶ added in v4.1.0
type OrderView struct {
model.Order
// User and Plan shadow the relations of model.Order, which are never
// loaded here.
User *OrderBuyerRef `json:"user,omitempty"`
Plan *OrderPlanRef `json:"plan,omitempty"`
}
OrderView is an order as the order list and detail routes answer it: the order's own columns, its plan's id and name, and, for an administrator, its buyer's id and e-mail. A plan or buyer that no longer exists is left out. The answers used to embed the buyer's whole v2_user row (subscription token and UUID included) and the whole v2_plan row.
type PackageHostMigrator ¶ added in v4.1.0
type PackageHostMigrator struct {
DB *gorm.DB
Hosts *pluginhost.Supervisor
// Now defaults to time.Now.
Now func() time.Time
// contains filtered or unexported fields
}
PackageHostMigrator runs the migration index of a started storage package through the migration ledger: one run per package lifecycle generation.
func (PackageHostMigrator) MigrateStartedHost ¶ added in v4.1.0
func (m PackageHostMigrator) MigrateStartedHost(ctx context.Context, ref pluginhost.ArtifactRef, generation uint64) error
MigrateStartedHost applies ref's migration index in the host that was just started for generation, verifies that the host applied exactly the steps of the verified index, and records the validation. Releases that do not declare kernel.storage.v1, or declare no steps, are left alone. A repeated call for the same generation, for example after a Control restart, resumes or confirms the recorded run instead of starting another one.
type PackageHostOperations ¶ added in v4.1.0
type PackageHostOperations struct {
DB *gorm.DB
// Storage provisions package storage for LeaseStorage; nil disables it.
Storage *packagestore.Store
// FallbackPublicKey verifies releases recorded without a trust root.
FallbackPublicKey ed25519.PublicKey
}
PackageHostOperations serves the session-scoped package bridge RPCs from the kernel database.
func (PackageHostOperations) AuthorizeCapability ¶ added in v4.1.0
func (o PackageHostOperations) AuthorizeCapability(ctx context.Context, host packagebridge.HostIdentity, capability string) error
AuthorizeCapability admits a host to a kernel contract method family on the same terms: the current generation of an official AnixOps package whose verified signed release declares capability.
func (PackageHostOperations) AuthorizeIdentity ¶ added in v4.1.0
func (o PackageHostOperations) AuthorizeIdentity(ctx context.Context, host packagebridge.HostIdentity) error
AuthorizeIdentity admits a host to KernelIdentity only when it is the current generation of an official AnixOps package whose signed release, verified again here, declares kernel.identity.v1.
func (PackageHostOperations) LeaseStorage ¶ added in v4.1.0
func (o PackageHostOperations) LeaseStorage(ctx context.Context, host packagebridge.HostIdentity) (packagebridge.StorageLease, error)
LeaseStorage provisions the calling host's storage from the storage capabilities of its signed release and returns fresh credentials. The host must be the current installation generation.
func (PackageHostOperations) PackageConfig ¶ added in v4.1.0
func (o PackageHostOperations) PackageConfig(ctx context.Context, host packagebridge.HostIdentity) (packagebridge.PackageConfig, error)
PackageConfig returns the calling host's route modes. The host must be the enabled control installation at its desired version and current lifecycle generation; any other host is fenced.
type PackageMigrationCheckpoint ¶
type PackageMigrationCheckpoint struct {
OpaqueCheckpoint string
ValidationDigest string
Complete bool
FailureCode string
}
PackageMigrationCheckpoint is an opaque host response persisted before the caller can act on that response. Its fields are intentionally not parsed by the kernel.
type PackageReport ¶ added in v4.2.0
type PackageReport struct {
NodeKind string `json:"node_kind"`
NodeID uint `json:"node_id"`
PluginID string `json:"plugin_id"`
Kind string `json:"kind"`
Version string `json:"version"`
Payload json.RawMessage `json:"payload"`
ObservedAt time.Time `json:"observed_at"`
ReceivedAt time.Time `json:"received_at"`
// Stale is true when the report is older than the kind allows (25
// minutes for systemd.services) at the time it was read.
Stale bool `json:"stale"`
}
PackageReport is the latest report of a node, plugin and kind, as the kernel stored it.
type PackageReportInput ¶ added in v4.2.0
type PackageReportInput struct {
NodeKind string
NodeID uint
PluginID string
Kind string
Version string
Payload []byte
// ObservedAt is zero when the Agent did not say; the kernel then uses
// the receive time.
ObservedAt time.Time
}
PackageReportInput is one PackageReport from an authenticated node.
type PackageReportRefusedError ¶ added in v4.2.0
PackageReportRefusedError is a permanent refusal of one report.
func (*PackageReportRefusedError) Error ¶ added in v4.2.0
func (e *PackageReportRefusedError) Error() string
type PackageRouteDefaultPackage ¶ added in v4.1.0
type PackageRouteDefaultPackage struct {
PackageID string `json:"package_id"`
// Batch is the rehearsal batch that signed the package off.
Batch int `json:"batch"`
// MinVersion is the oldest release the default applies to: the
// rehearsed one. Older releases (the signed 4.0 packages) stay legacy.
MinVersion string `json:"min_version"`
Routes []string `json:"routes"`
}
PackageRouteDefaultPackage is one package of config/package-route-defaults.json.
type PackageRouteDefaultState ¶ added in v4.1.0
type PackageRouteDefaultState struct {
// Policy is package_routes.default_mode.
Policy string `json:"policy"`
// Routes is the number of the package's routes in the default set.
Routes int `json:"routes"`
// MinVersion is the release the default needs ("" when the package has
// no default routes).
MinVersion string `json:"min_version,omitempty"`
// Source is what the package's unstored default routes get: default,
// kill-switch or package-too-old ("" without default routes).
Source string `json:"source,omitempty"`
// Note explains a default that does not apply.
Note string `json:"note,omitempty"`
}
PackageRouteDefaultState is how the default policy applies to one installed package.
type PackageRouteDefaults ¶ added in v4.1.0
type PackageRouteDefaults struct {
Format string `json:"format"`
DefaultMode string `json:"default_mode"`
Packages []PackageRouteDefaultPackage `json:"packages"`
// contains filtered or unexported fields
}
PackageRouteDefaults is config/package-route-defaults.json.
func LoadPackageRouteDefaults ¶ added in v4.1.0
func LoadPackageRouteDefaults() (*PackageRouteDefaults, error)
LoadPackageRouteDefaults returns the embedded default set.
func (*PackageRouteDefaults) Includes ¶ added in v4.1.0
func (d *PackageRouteDefaults) Includes(packageID, route string) bool
Includes reports whether route of packageID is in the default set.
func (*PackageRouteDefaults) Package ¶ added in v4.1.0
func (d *PackageRouteDefaults) Package(packageID string) (PackageRouteDefaultPackage, bool)
Package returns a package's defaults.
func (*PackageRouteDefaults) RouteCount ¶ added in v4.1.0
func (d *PackageRouteDefaults) RouteCount() int
RouteCount is the number of routes in the default set.
type PackageRouteModes ¶ added in v4.1.0
type PackageRouteModes struct {
PackageID string `json:"package_id"`
InstallationID uint `json:"installation_id"`
Version string `json:"version"`
Enabled bool `json:"enabled"`
ConfigRevision int64 `json:"config_revision"`
Error string `json:"error,omitempty"`
// Defaults is how the rehearsed default set applies to the package.
Defaults PackageRouteDefaultState `json:"defaults"`
Routes []RouteModeEntry `json:"routes"`
}
PackageRouteModes is one package's routes and their modes.
type PackageStorageGrants ¶ added in v4.1.0
type PackageStorageGrants struct {
Storage bool
// AdoptTables are existing tables the package role may read and write.
AdoptTables []string
// Views are kernel API views the package role may read.
Views []string
}
PackageStorageGrants is what the storage capabilities of a verified manifest ask the kernel for.
func EffectiveStorageGrants ¶ added in v4.1.0
func EffectiveStorageGrants(db *gorm.DB, grants PackageStorageGrants) (PackageStorageGrants, error)
EffectiveStorageGrants are the grants of a verified manifest the kernel honours now: an adoption of a finalized-adoptable table only once its split is finalized (nodesecrets.AdoptionAllowed), and a view of the split's remainder only once it exists (packagestore.FinalizedViewAvailable). What it leaves out is left out of the lease, as if not declared; the package's native routes for it stay legacy (mode_unsupported).
func StorageGrants ¶ added in v4.1.0
func StorageGrants(manifest PluginManifest) PackageStorageGrants
StorageGrants extracts the storage grants from a manifest whose capabilities already passed validation.
type PanelAdminTunnelItem ¶
type PanelAdminTunnelItem struct {
ID uint `json:"id"`
Name string `json:"name"`
InNodeID uint `json:"inNodeId"`
OutNodeID *uint `json:"outNodeId"`
Type int `json:"type"`
Flow int `json:"flow"`
TrafficRatio float64 `json:"trafficRatio"`
InterfaceName string `json:"interfaceName"`
Protocol string `json:"protocol"`
TCPListenAddr string `json:"tcpListenAddr"`
UDPListenAddr string `json:"udpListenAddr"`
InIP string `json:"inIp"`
OutIP string `json:"outIp"`
Status int `json:"status"`
CreatedTime int64 `json:"createdTime"`
UpdatedTime int64 `json:"updatedTime"`
}
type PanelForwardFlowData ¶
type PanelForwardInput ¶
type PanelForwardListItem ¶
type PanelForwardListItem struct {
ID uint `json:"id"`
Name string `json:"name"`
TunnelID uint `json:"tunnelId"`
TunnelName string `json:"tunnelName"`
InIP string `json:"inIp"`
InPort int `json:"inPort"`
RemoteAddr string `json:"remoteAddr"`
InterfaceName string `json:"interfaceName"`
Strategy string `json:"strategy"`
Status int `json:"status"`
InFlow int64 `json:"inFlow"`
OutFlow int64 `json:"outFlow"`
RuntimeBackend string `json:"runtimeBackend"`
RuntimeStatus int `json:"runtimeStatus"`
RuntimeMessage string `json:"runtimeMessage"`
LastRuntimeSyncTime int64 `json:"lastRuntimeSyncTime"`
CreatedTime int64 `json:"createdTime"`
UpdatedTime int64 `json:"updatedTime"`
UserName string `json:"userName"`
UserID uint `json:"userId"`
Inx int `json:"inx"`
}
type PanelForwardOrderUpdate ¶
type PanelForwardRuntimeDoctorSummary ¶
type PanelForwardRuntimeDoctorSummary struct {
PanelForwardRuntimeStatusSummary
Commands PanelForwardRuntimeCommandHints `json:"commands"`
}
type PanelForwardRuntimeJobExecutor ¶
type PanelForwardRuntimeJobExecutor struct {
// contains filtered or unexported fields
}
func NewPanelForwardRuntimeJobExecutor ¶
func NewPanelForwardRuntimeJobExecutor(db *gorm.DB) *PanelForwardRuntimeJobExecutor
func (*PanelForwardRuntimeJobExecutor) RunPendingJobs ¶
func (e *PanelForwardRuntimeJobExecutor) RunPendingJobs(ctx context.Context) error
func (*PanelForwardRuntimeJobExecutor) Start ¶
func (e *PanelForwardRuntimeJobExecutor) Start(ctx context.Context)
type PanelForwardRuntimeService ¶
type PanelForwardRuntimeService struct {
// contains filtered or unexported fields
}
func NewPanelForwardRuntimeService ¶
func NewPanelForwardRuntimeService(db *gorm.DB) *PanelForwardRuntimeService
func (*PanelForwardRuntimeService) Apply ¶
func (s *PanelForwardRuntimeService) Apply(ctx context.Context, action string, forward *model.Forward, tunnel *model.ForwardTunnel) (*panelForwardRuntimeResult, error)
func (*PanelForwardRuntimeService) BackendForForward ¶ added in v4.1.0
func (s *PanelForwardRuntimeService) BackendForForward(forward *model.Forward) (string, error)
BackendForForward answers the runtime backend a forward's change runs on: the forward's own, else the backend in force.
func (*PanelForwardRuntimeService) DiagnoseLocalOperator ¶
func (s *PanelForwardRuntimeService) DiagnoseLocalOperator(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
func (*PanelForwardRuntimeService) DiagnoseNodeXOperator ¶
func (s *PanelForwardRuntimeService) DiagnoseNodeXOperator(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
func (*PanelForwardRuntimeService) DiagnosePanelRuntime ¶
func (s *PanelForwardRuntimeService) DiagnosePanelRuntime(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
func (*PanelForwardRuntimeService) ForwardsToMoveToBackend ¶ added in v4.1.0
func (s *PanelForwardRuntimeService) ForwardsToMoveToBackend(targetBackend string) ([]model.Forward, error)
SyncForwardsToBackend re-synces all active forwards to the current backend. Used when the admin switches between NodeX and Local mode. ForwardsToMoveToBackend lists the active forwards not on targetBackend, oldest first: what the backend sync re-applies.
func (*PanelForwardRuntimeService) GetLocalOperatorStatus ¶
func (s *PanelForwardRuntimeService) GetLocalOperatorStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
func (*PanelForwardRuntimeService) GetNodeXOperatorStatus ¶
func (s *PanelForwardRuntimeService) GetNodeXOperatorStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
func (*PanelForwardRuntimeService) GetNodeXRuntimeStatus ¶
func (s *PanelForwardRuntimeService) GetNodeXRuntimeStatus(ctx context.Context) (*nodeXForwardRuntimeStatus, error)
func (*PanelForwardRuntimeService) GetPanelRuntimeStatus ¶
func (s *PanelForwardRuntimeService) GetPanelRuntimeStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
func (*PanelForwardRuntimeService) MarkForwardsPendingForBackend ¶
func (s *PanelForwardRuntimeService) MarkForwardsPendingForBackend(targetBackend string) (int64, error)
MarkForwardsPendingForBackend resets forwards that need re-sync to pending status. Call this after a backend switch to mark mismatched forwards for later re-sync.
func (*PanelForwardRuntimeService) MoveForwardToBackend ¶ added in v4.1.0
func (s *PanelForwardRuntimeService) MoveForwardToBackend(forwardID uint, backend string) error
MoveForwardToBackend records that a forward now runs on backend; the change is applied by the next sync of the forward.
func (*PanelForwardRuntimeService) ResolveBackend ¶ added in v4.1.0
func (s *PanelForwardRuntimeService) ResolveBackend() (string, error)
ResolveBackend answers the runtime backend in force.
func (*PanelForwardRuntimeService) SyncForwardsToBackend ¶
func (s *PanelForwardRuntimeService) SyncForwardsToBackend(targetBackend string) (synced int, failed int, err error)
type PanelForwardRuntimeStatusSnapshot ¶
type PanelForwardRuntimeStatusSnapshot struct {
OK bool `json:"ok"`
StatusCode int `json:"statusCode,omitempty"`
Error string `json:"error,omitempty"`
Version string `json:"version,omitempty"`
AuthRequired *bool `json:"authRequired,omitempty"`
ExecutePath string `json:"executePath,omitempty"`
StatusPath string `json:"statusPath,omitempty"`
Supports *nodeXForwardRuntimeSupportState `json:"supports,omitempty"`
Modes *nodeXForwardRuntimeModes `json:"modes,omitempty"`
Issues []string `json:"issues,omitempty"`
}
type PanelForwardRuntimeStatusSummary ¶
type PanelForwardRuntimeStatusSummary struct {
BaseURL string `json:"baseUrl,omitempty"`
CheckedAt string `json:"checkedAt"`
Config PanelForwardRuntimeConfigState `json:"config"`
Attachment PanelForwardRuntimeAttachmentState `json:"attachment"`
Reachability PanelForwardRuntimeReadiness `json:"reachability"`
RuntimeReady PanelForwardRuntimeReadiness `json:"runtimeReady"`
Summary string `json:"summary,omitempty"`
Warnings []string `json:"warnings,omitempty"`
Health PanelForwardRuntimeProbe `json:"health"`
RuntimeStatus PanelForwardRuntimeStatusSnapshot `json:"runtimeStatus"`
LocalAnsible *nodeXForwardRuntimeAnsibleStatus `json:"localAnsible,omitempty"`
}
type PanelForwardService ¶
type PanelForwardService struct {
// contains filtered or unexported fields
}
func NewPanelForwardService ¶
func NewPanelForwardService(db *gorm.DB) *PanelForwardService
func (*PanelForwardService) ActiveTunnelForwardIDs ¶ added in v4.1.0
func (s *PanelForwardService) ActiveTunnelForwardIDs(tunnelID uint) ([]uint, error)
ActiveTunnelForwardIDs lists the active forwards of a tunnel, oldest first: what a tunnel change re-applies.
func (*PanelForwardService) ApplyForwardRuntime ¶ added in v4.1.0
func (s *PanelForwardService) ApplyForwardRuntime(ctx context.Context, record *model.Forward, action string) (*ForwardRuntimeOutcome, error)
ApplyForwardRuntime applies one action for a forward on its node through the runtime backend in force (NodeX synchronously, or a local Ansible or clean agent job) and records the runtime columns of the forward's row, as every legacy forward change does. The legacy routes and the KernelNodeOps forward.apply executor run it alike; the status column is the caller's.
func (*PanelForwardService) ApplyForwardTrafficSnapshots ¶
func (s *PanelForwardService) ApplyForwardTrafficSnapshots(records []PanelForwardTrafficSnapshot) error
func (*PanelForwardService) AssignUserTunnel ¶
func (s *PanelForwardService) AssignUserTunnel(input PanelUserTunnelInput) error
func (*PanelForwardService) CreateTunnel ¶
func (s *PanelForwardService) CreateTunnel(input PanelTunnelInput) (*PanelAdminTunnelItem, error)
func (*PanelForwardService) DeleteTunnel ¶
func (s *PanelForwardService) DeleteTunnel(id uint) error
func (*PanelForwardService) DiagnoseForwardTargets ¶ added in v4.1.0
func (s *PanelForwardService) DiagnoseForwardTargets(ctx context.Context, probes DiagnosisProbes, forwardID uint, publicOnly bool) (*DiagnosisReport, error)
DiagnoseForwardTargets diagnoses forward forwardID from Control for the kernel: the forward is not scoped to an actor, and with publicOnly only public targets are dialled, as for a user.
func (*PanelForwardService) DiagnoseLocalOperator ¶
func (s *PanelForwardService) DiagnoseLocalOperator(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
func (*PanelForwardService) DiagnoseNodeXOperator ¶
func (s *PanelForwardService) DiagnoseNodeXOperator(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
func (*PanelForwardService) DiagnoseRuntime ¶
func (s *PanelForwardService) DiagnoseRuntime(ctx context.Context) (*PanelForwardRuntimeDoctorSummary, error)
func (*PanelForwardService) DiagnoseTunnel ¶
func (s *PanelForwardService) DiagnoseTunnel(id uint) (*TunnelDiagnosisReport, error)
DiagnoseTunnel diagnoses a tunnel from Control. It is DiagnoseTunnelContext without a deadline.
func (*PanelForwardService) DiagnoseTunnelContext ¶ added in v4.1.0
func (s *PanelForwardService) DiagnoseTunnelContext(ctx context.Context, probes DiagnosisProbes, id uint) (*TunnelDiagnosisReport, error)
DiagnoseTunnelContext diagnoses a tunnel from Control: it dials the tunnel's execution node (job backends), or its entry node and, for a two-hop tunnel, its exit node. When ctx ends it returns the probes that completed and ctx's error.
func (*PanelForwardService) GetForwardWithTunnel ¶ added in v4.1.0
func (s *PanelForwardService) GetForwardWithTunnel(id uint) (*model.Forward, error)
GetForwardWithTunnel loads a panel forward with its tunnel, for the runtime: ErrPanelForwardNotFound when there is none.
func (*PanelForwardService) GetLocalOperatorStatus ¶
func (s *PanelForwardService) GetLocalOperatorStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
func (*PanelForwardService) GetNodeXOperatorStatus ¶
func (s *PanelForwardService) GetNodeXOperatorStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
func (*PanelForwardService) GetRuntimeStatus ¶
func (s *PanelForwardService) GetRuntimeStatus(ctx context.Context) (*PanelForwardRuntimeStatusSummary, error)
func (*PanelForwardService) ListAdminTunnels ¶
func (s *PanelForwardService) ListAdminTunnels() ([]PanelAdminTunnelItem, error)
func (*PanelForwardService) ListForwards ¶
func (s *PanelForwardService) ListForwards(userID uint, isAdmin bool) ([]PanelForwardListItem, error)
func (*PanelForwardService) ListTunnels ¶
func (s *PanelForwardService) ListTunnels(userID uint, isAdmin bool) ([]PanelTunnelListItem, error)
func (*PanelForwardService) ListUserTunnels ¶
func (s *PanelForwardService) ListUserTunnels(query PanelUserTunnelQueryInput) ([]PanelUserTunnelDetailItem, error)
func (*PanelForwardService) RecordForwardTraffic ¶
func (s *PanelForwardService) RecordForwardTraffic(records []PanelForwardTrafficRecord) error
func (*PanelForwardService) ResetUserTunnelTraffic ¶
func (s *PanelForwardService) ResetUserTunnelTraffic(id uint) error
func (*PanelForwardService) RuntimeService ¶
func (s *PanelForwardService) RuntimeService() *PanelForwardRuntimeService
func (*PanelForwardService) UpdateOrder ¶
func (s *PanelForwardService) UpdateOrder(userID uint, isAdmin bool, updates []PanelForwardOrderUpdate) error
func (*PanelForwardService) UploadFluxForwardFlow ¶
func (s *PanelForwardService) UploadFluxForwardFlow(data PanelForwardFlowData) error
type PanelForwardUpdateInput ¶
type PanelRuntimeJobFilter ¶
type PanelTunnelInput ¶
type PanelTunnelInput struct {
Name string `json:"name"`
InNodeID uint `json:"inNodeId"`
OutNodeID *uint `json:"outNodeId"`
Type int `json:"type"`
Flow int `json:"flow"`
TrafficRatio *float64 `json:"trafficRatio"`
InterfaceName string `json:"interfaceName"`
Protocol string `json:"protocol"`
TCPListenAddr string `json:"tcpListenAddr"`
UDPListenAddr string `json:"udpListenAddr"`
}
type PanelTunnelListItem ¶
type PanelTunnelUpdateInput ¶
type PanelTunnelUpdateInput struct {
ID uint `json:"id"`
Name string `json:"name"`
Flow int `json:"flow"`
TrafficRatio *float64 `json:"trafficRatio"`
InterfaceName string `json:"interfaceName"`
Protocol string `json:"protocol"`
TCPListenAddr string `json:"tcpListenAddr"`
UDPListenAddr string `json:"udpListenAddr"`
}
type PanelUserTunnelDetailItem ¶
type PanelUserTunnelDetailItem struct {
ID uint `json:"id"`
UserID uint `json:"userId"`
TunnelID uint `json:"tunnelId"`
Flow int64 `json:"flow"`
Num int `json:"num"`
FlowResetTime int64 `json:"flowResetTime"`
ExpTime int64 `json:"expTime"`
SpeedID *uint `json:"speedId"`
SpeedLimitName string `json:"speedLimitName"`
Speed int64 `json:"speed"`
TunnelName string `json:"tunnelName"`
TunnelFlow int `json:"tunnelFlow"`
InFlow int64 `json:"inFlow"`
OutFlow int64 `json:"outFlow"`
Status int `json:"status"`
}
type PanelUserTunnelInput ¶
type PanelUserTunnelQueryInput ¶
type PanelUserTunnelQueryInput struct {
UserID uint `json:"userId"`
}
type PaymentGatewayService ¶
type PaymentGatewayService struct {
// contains filtered or unexported fields
}
PaymentGatewayService 支付网关服务
func NewPaymentGatewayService ¶
func NewPaymentGatewayService(db *gorm.DB) *PaymentGatewayService
NewPaymentGatewayService 创建服务
func (*PaymentGatewayService) CalculateFee ¶
func (s *PaymentGatewayService) CalculateFee(gateway *model.PaymentGateway, amount float64) float64
CalculateFee 计算手续费
func (*PaymentGatewayService) CheckOrderPayable ¶ added in v4.1.0
func (s *PaymentGatewayService) CheckOrderPayable(orderID, userID uint, amount float64) error
CheckOrderPayable checks that a payment of amount (yuan) that userID creates for orderID pays it: the order is the caller's, still pending, and the amount is its total. A payment record names the order it pays, and a successful callback marks that order paid and activates it, so a record may not name another user's order or pay less than its total.
func (*PaymentGatewayService) Create ¶
func (s *PaymentGatewayService) Create(gateway *model.PaymentGateway) error
Create 创建网关
func (*PaymentGatewayService) CreateRecord ¶
func (s *PaymentGatewayService) CreateRecord(record *model.PaymentRecord) error
CreateRecord 创建支付记录
func (*PaymentGatewayService) Delete ¶
func (s *PaymentGatewayService) Delete(id uint) error
Delete 删除网关
func (*PaymentGatewayService) FinishPaidOrder ¶ added in v4.1.0
func (s *PaymentGatewayService) FinishPaidOrder(record model.PaymentRecord)
FinishPaidOrder applies a payment record that is already paid to its order, once: a repeated callback calls it, so that a payment recorded without its order completion (the payment module records the payment, then calls KernelOrder; a failure in between leaves the order pending) converges whichever side serves the repeat. A record applied before, or not paid, or without an order, changes nothing.
func (*PaymentGatewayService) GenerateTradeNo ¶
func (s *PaymentGatewayService) GenerateTradeNo() string
GenerateTradeNo 生成商户订单号
func (*PaymentGatewayService) GetByID ¶
func (s *PaymentGatewayService) GetByID(id uint) (*model.PaymentGateway, error)
GetByID 根据ID获取网关
func (*PaymentGatewayService) GetByType ¶
func (s *PaymentGatewayService) GetByType(gatewayType string) (*model.PaymentGateway, error)
GetByType 根据类型获取网关
func (*PaymentGatewayService) GetChannels ¶
func (s *PaymentGatewayService) GetChannels() ([]*model.PaymentChannel, error)
GetChannels 获取支付渠道 (前端显示用)
func (*PaymentGatewayService) GetEnabled ¶
func (s *PaymentGatewayService) GetEnabled() ([]*model.PaymentGateway, error)
GetEnabled 获取启用的网关
func (*PaymentGatewayService) GetRecordByTradeNo ¶
func (s *PaymentGatewayService) GetRecordByTradeNo(tradeNo string) (*model.PaymentRecord, error)
GetRecordByTradeNo 根据订单号获取记录
func (*PaymentGatewayService) GetStats ¶
func (s *PaymentGatewayService) GetStats(start, end time.Time) (*PaymentStats, error)
GetStats 获取支付统计
func (*PaymentGatewayService) GetUserRecords ¶
func (s *PaymentGatewayService) GetUserRecords(userID uint, page, pageSize int) ([]*model.PaymentRecord, int64, error)
GetUserRecords 获取用户支付记录
func (*PaymentGatewayService) List ¶
func (s *PaymentGatewayService) List() ([]*model.PaymentGateway, error)
List 获取网关列表
func (*PaymentGatewayService) ListRecords ¶
func (s *PaymentGatewayService) ListRecords(page, pageSize int, status *int, gatewayType string) ([]*model.PaymentRecord, int64, error)
ListRecords 获取支付记录列表
func (*PaymentGatewayService) MarkOrderPaid ¶
func (s *PaymentGatewayService) MarkOrderPaid(tradeNo string, gatewayTradeNo string, notifyData string) error
MarkOrderPaid 标记支付并更新订单状态 (事务)
func (*PaymentGatewayService) MarkOrderPaidIfCovered ¶ added in v4.1.0
func (s *PaymentGatewayService) MarkOrderPaidIfCovered(tradeNo string, gatewayTradeNo string, notifyData string, covers func(model.PaymentRecord) error) error
MarkOrderPaidIfCovered marks the payment paid, as MarkOrderPaid does, only if covers accepts its pending record, read inside the transaction. covers returns an error wrapping ErrPaymentNotCovered to refuse it.
func (*PaymentGatewayService) MarkOrderPaidWithAmount ¶
func (s *PaymentGatewayService) MarkOrderPaidWithAmount(tradeNo string, gatewayTradeNo string, notifyData string, paidAmount *float64) error
MarkOrderPaidWithAmount 标记支付并核对回调金额。
func (*PaymentGatewayService) ParseConfig ¶
func (s *PaymentGatewayService) ParseConfig(gateway *model.PaymentGateway) (any, error)
ParseConfig 解析网关配置
func (*PaymentGatewayService) Toggle ¶
func (s *PaymentGatewayService) Toggle(id uint, enabled bool) error
Toggle 切换网关状态
func (*PaymentGatewayService) Update ¶
func (s *PaymentGatewayService) Update(gateway *model.PaymentGateway) error
Update 更新网关
func (*PaymentGatewayService) ValidateAmount ¶
func (s *PaymentGatewayService) ValidateAmount(gateway *model.PaymentGateway, amount float64) error
ValidateAmount 验证金额范围
func (*PaymentGatewayService) ValidateGatewayUsable ¶
func (s *PaymentGatewayService) ValidateGatewayUsable(gateway *model.PaymentGateway) error
ValidateGatewayUsable verifies that a gateway can be shown to users and used to create new payment records.
type PaymentStats ¶
type PaymentStats struct {
TotalAmount float64 `json:"total_amount"`
TotalCount int64 `json:"total_count"`
PendingAmount float64 `json:"pending_amount"`
PendingCount int64 `json:"pending_count"`
}
PaymentStats 支付统计
type PlanService ¶
type PlanService struct {
// contains filtered or unexported fields
}
PlanService 管理套餐
func (*PlanService) AssignToUser ¶
func (s *PlanService) AssignToUser(planID, userID uint, expireAt *int64, requestID string) error
AssignToUser 将套餐分配给用户(同步修改用户记录),并写事件。requestID (PlanAssignmentRequestID) applies a retried assignment once; the event is written again.
type PluginConfigurationSemanticValidator ¶
type PluginConfigurationSemanticValidator func(pluginID, version string, canonicalConfig json.RawMessage) error
PluginConfigurationSemanticValidator supplies optional, version-bound package semantics that cannot be expressed safely in JSON Schema.
type PluginConfigurationTxHook ¶
type PluginConfigurationTxHook func(tx *gorm.DB, installation model.PluginInstallation, configuration model.PluginConfiguration) error
type PluginControlRouteResolution ¶
type PluginControlRouteResolution struct {
PluginID string `json:"plugin_id"`
Version string `json:"version"`
InstallationID uint `json:"installation_id"`
Generation uint64 `json:"generation"`
Route string `json:"route"`
MatchedRoute string `json:"matched_route"`
Permission string `json:"permission"`
}
type PluginDependencyExecutionPlan ¶
type PluginDependencyExecutionPlan struct {
Target string `json:"target"`
RootID string `json:"root_id"`
Order []string `json:"order"`
Steps []PluginDependencyExecutionStep `json:"steps"`
}
PluginDependencyExecutionPlan is the dependency-first closure used by the Control lifecycle worker. Unlike the compatibility resolver, it can select the latest registered target-compatible release for a missing dependency so an administrator can enable one root package without first hand-installing every package in its closure.
An existing installation always pins its desired version. That makes an upgrade deterministic and prevents a newly published dependency release from silently changing an already configured package.
func ResolvePluginDependencyExecutionPlan ¶
func ResolvePluginDependencyExecutionPlan(db *gorm.DB, rootRelease model.PluginRelease, target string) (*PluginDependencyExecutionPlan, error)
ResolvePluginDependencyExecutionPlan resolves a root release and all of its transitive dependencies into a stable dependency-first execution plan. It validates the selected stored manifests, including registered trust roots, but does not mutate installation intent.
type PluginDependencyExecutionStep ¶
type PluginDependencyExecutionStep struct {
PluginID string `json:"plugin_id"`
Release model.PluginRelease `json:"release"`
Manifest PluginManifest `json:"manifest"`
Installation *model.PluginInstallation `json:"installation,omitempty"`
}
PluginDependencyExecutionStep binds one graph vertex to the immutable release that an execution plan will use. Installation is nil when the package has not been installed on the target yet.
type PluginDependencyResolution ¶
type PluginDependencyResolution struct {
Roots []string `json:"roots"`
Order []string `json:"order"`
Ordered []PluginManifest `json:"ordered"`
}
PluginDependencyResolution is the deterministic execution plan for a set of selected plugin releases. Ordered and Order contain the same nodes; the former is convenient for lifecycle execution and the latter is convenient for persistence, logging, and test assertions.
Dependencies always precede their dependents. Nodes that are otherwise unrelated are ordered by plugin ID, making the result independent of map, input-slice, and manifest-declaration order.
func ResolvePluginDependencyGraph ¶
func ResolvePluginDependencyGraph(manifests []PluginManifest, rootIDs []string) (*PluginDependencyResolution, error)
ResolvePluginDependencyGraph resolves root plugin IDs from a selected manifest set. The returned order is a stable dependency-first topological order. A shared dependency is emitted once, even when multiple roots depend on it.
func ResolvePluginInstallationDependencyGraph ¶
func ResolvePluginInstallationDependencyGraph(db *gorm.DB, rootRelease model.PluginRelease, target string) (*PluginDependencyResolution, error)
ResolvePluginInstallationDependencyGraph loads the selected desired release for every dependency from the Control database, verifies the stored release metadata, and then delegates graph validation/order to ResolvePluginDependencyGraph. A dependency installation may be disabled: this function is a preflight graph check, not an enable operation. The existing ValidatePluginInstallationPlan check still enforces that every dependency is enabled before production intent is accepted.
Registered releases carry a trust-root fingerprint and are re-verified from the stored trust-root row. Rows created by the pre-signature 3.x migration without a fingerprint retain the existing compatibility behavior and are checked through DecodePluginReleaseManifest.
type PluginDependencyResolver ¶
type PluginDependencyResolver struct {
// contains filtered or unexported fields
}
PluginDependencyResolver indexes one selected release per plugin ID. A release catalog may contain many versions, but callers must select the version to execute before constructing this resolver.
func NewPluginDependencyResolver ¶
func NewPluginDependencyResolver(manifests []PluginManifest) (*PluginDependencyResolver, error)
NewPluginDependencyResolver validates and indexes the selected manifests. It intentionally performs graph relationship validation here, while full signature/artifact validation remains the responsibility of RegisterPluginRelease/VerifyStoredPluginRelease.
func (*PluginDependencyResolver) Resolve ¶
func (r *PluginDependencyResolver) Resolve(rootIDs []string) (*PluginDependencyResolution, error)
Resolve computes the dependency closure and a deterministic topological order for rootIDs.
type PluginEntrypoint ¶
type PluginInstallationStatus ¶
type PluginInstallationStatus struct {
ID uint `json:"id"`
PluginID string `json:"plugin_id"`
Target string `json:"target"`
DesiredVersion string `json:"desired_version"`
ObservedVersion string `json:"observed_version"`
PreviousVersion string `json:"previous_version"`
State string `json:"state"`
Health string `json:"health"`
Enabled bool `json:"enabled"`
LifecycleGeneration int64 `json:"lifecycle_generation"`
ConfigRevision int64 `json:"config_revision"`
HasError bool `json:"has_error"`
LastError string `json:"last_error,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DisabledAt *time.Time `json:"disabled_at,omitempty"`
}
PluginInstallationStatus is the public projection of a plugin installation. Installation LastError can originate in a Control executor or from an Agent lifecycle result, so it is reduced to a stable state summary before it crosses an HTTP boundary.
func PublicPluginInstallation ¶
func PublicPluginInstallation(installation model.PluginInstallation) PluginInstallationStatus
PublicPluginInstallation keeps package lifecycle metadata useful to the WebUI while withholding raw executor and Agent diagnostics.
type PluginManifest ¶
type PluginManifest struct {
ID string `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
APIVersion string `json:"api_version"`
Publisher string `json:"publisher"`
Targets []string `json:"targets"`
Architectures []string `json:"architectures"`
ArtifactSHA256 string `json:"artifact_sha256"`
Capabilities []string `json:"capabilities"`
Dependencies []string `json:"dependencies"`
Conflicts []string `json:"conflicts"`
Permissions []string `json:"permissions"`
ConfigSchema json.RawMessage `json:"config_schema"`
SecretFields []string `json:"secret_fields"`
Entrypoints map[string]string `json:"entrypoints"`
Migration int64 `json:"migration_version"`
ControlRoutes []string `json:"control_routes"`
FrontendSHA256 string `json:"frontend_sha256"`
WebUI *PluginWebUI `json:"webui,omitempty"`
ControlEntrypoint *PluginEntrypoint `json:"control_entrypoint,omitempty"`
AgentEntrypoint *PluginEntrypoint `json:"agent_entrypoint,omitempty"`
Migrations *PluginMigrations `json:"migrations,omitempty"`
CompatibilityRoutes *PluginCompatibilityRoutes `json:"compatibility_routes,omitempty"`
RouteContractDigest string `json:"route_contract_digest,omitempty"`
RuntimeAPIVersion string `json:"runtime_api_version,omitempty"`
}
func DecodePluginReleaseManifest ¶
func DecodePluginReleaseManifest(release model.PluginRelease) (*PluginManifest, error)
ValidatePluginReleaseTarget verifies the internally persisted release metadata before it is used to create desired state. Releases are immutable, so a mismatch here indicates corrupt or manually modified kernel data.
func VerifyPluginRelease ¶
func VerifyPluginRelease(manifestJSON, signature string, publicKey ed25519.PublicKey) (*PluginManifest, error)
func VerifyStoredPluginRelease ¶
func VerifyStoredPluginRelease(db *gorm.DB, release model.PluginRelease, fallback ed25519.PublicKey) (*PluginManifest, error)
func (PluginManifest) Validate ¶
func (m PluginManifest) Validate() error
type PluginMigrations ¶
type PluginWebUI ¶
type PluginWebUI struct {
Bundle PluginWebUIBundle `json:"bundle"`
Permissions []string `json:"permissions"`
Menus []PluginWebUIMenu `json:"menus"`
Routes []PluginWebUIRoute `json:"routes"`
}
PluginWebUI describes a signed, declarative administrator extension. Bundle paths are relative to the verified plugin artifact; they are not URLs and are never fetched directly by the control kernel.
type PluginWebUIBundle ¶
type PluginWebUIMenu ¶
type PluginWebUIRoute ¶
type ProxyNodeCredentials ¶ added in v4.1.0
ProxyNodeCredentials are a proxy node's API key and shared secret, as generated or typed; an empty one is not issued.
func GenerateProxyNodeCredentials ¶ added in v4.1.0
func GenerateProxyNodeCredentials(apiKey, secret bool) (ProxyNodeCredentials, error)
GenerateProxyNodeCredentials generates the credentials of a proxy node: 32 random bytes, hex encoded, each.
func (ProxyNodeCredentials) Apply ¶ added in v4.1.0
func (c ProxyNodeCredentials) Apply(node *model.Node)
Apply sets the credentials on a node row about to be written: the key, its hash and the secret.
type RawNodeConfigValidation ¶ added in v4.1.0
type RawNodeConfigValidation struct {
Config map[string]any
// Normalized is the configuration re-encoded, as the routes store it.
Normalized []byte
// Warnings are what the validation route answers besides validity.
Warnings []string
}
RawNodeConfigValidation is a validated raw configuration.
func ValidateRawNodeConfig ¶ added in v4.1.0
func ValidateRawNodeConfig(raw any) (*RawNodeConfigValidation, error)
ValidateRawNodeConfig runs the raw configuration validators of the node routes: the configuration must be a JSON object (ErrRawNodeConfigNotObject or the decoding error), and a WireGuard configuration must be valid (ErrInvalidNodeProtocol). A configuration without server_port is valid with a warning.
type RegistrationPolicy ¶
type RegistrationPolicy struct {
Enabled bool
RequireInvite bool
AllowedEmailDomains []string
BlockedEmailDomains []string
}
func ResolveRegistrationPolicy ¶
func ResolveRegistrationPolicy(cfg *config.Config) RegistrationPolicy
type RetireCounts ¶ added in v4.1.0
type RetireCounts struct {
CredentialsRevoked int64
SecretsDeleted int64
WireGuardPeersDeleted int64
ProtocolsDeleted int64
SubscriptionLinksDeleted int64
}
RetireCounts is what a retirement removed.
func RetireForwardNodeTx ¶ added in v4.1.0
func RetireForwardNodeTx(tx *gorm.DB, nodeID uint) (RetireCounts, error)
RetireForwardNodeTx removes what the kernel holds for a forward node being deleted: its token in the split table and its agent certificates and enrollments (node_deleted). The node row is the caller's.
func RetireProtocolTx ¶ added in v4.1.0
func RetireProtocolTx(tx *gorm.DB, protocolIDs ...uint) (RetireCounts, error)
RetireProtocolTx removes what goes with node protocols being deleted: their users' WireGuard peers, their subscription group links and their secrets in the split table. The protocol rows themselves are the caller's: the legacy deletion removes them in the same transaction, a package after its RetireProtocol succeeded.
func RetireProxyNodeTx ¶ added in v4.1.0
func RetireProxyNodeTx(tx *gorm.DB, nodeID uint) (RetireCounts, error)
RetireProxyNodeTx removes what the kernel holds for a proxy node being deleted: its protocols, with their peers, links and secrets (RetireProtocolTx), its credentials and raw configuration secrets in the split tables, and its agent certificates and enrollments (node_deleted). The node row is the caller's.
type RouteCatalogEntry ¶ added in v4.1.0
type RouteCatalogEntry struct {
Method string `json:"method"`
Path string `json:"path"`
PackageID string `json:"package_id"`
RouteID string `json:"route_id"`
Mode string `json:"mode"`
Reason string `json:"reason,omitempty"`
}
RouteCatalogEntry is one route of config/package-extraction.json.
type RouteHostObservation ¶ added in v4.1.0
type RouteHostObservation struct {
Mode string `json:"mode"`
Effective string `json:"effective"`
NativeTotal uint64 `json:"native_total"`
NativeErrors uint64 `json:"native_errors"`
ShadowTotal uint64 `json:"shadow_total"`
ShadowMismatch uint64 `json:"shadow_mismatch"`
ShadowErrors uint64 `json:"shadow_errors"`
ShadowSkipped uint64 `json:"shadow_skipped"`
// MismatchRate is ShadowMismatch / ShadowTotal (0 without shadow
// runs).
MismatchRate float64 `json:"mismatch_rate"`
// LastMismatchAt is when the host last saw a mismatch.
LastMismatchAt *time.Time `json:"last_mismatch_at,omitempty"`
}
RouteHostObservation is what a package host reports about one route in its health details: the mode it applies and its native and shadow counters since the host started.
func (RouteHostObservation) WithRate ¶ added in v4.1.0
func (o RouteHostObservation) WithRate() RouteHostObservation
WithRate returns the observation with MismatchRate computed.
type RouteModeActor ¶ added in v4.1.0
RouteModeActor is who changes route modes, as the audit log and the revision history record it. UserID 0 is the command line.
type RouteModeAdmin ¶ added in v4.1.0
type RouteModeAdmin struct {
DB *gorm.DB
PublicKey ed25519.PublicKey
// Catalog defaults to PackageRouteCatalog.
Catalog map[string]RouteCatalogEntry
// Now defaults to time.Now.
Now func() time.Time
}
RouteModeAdmin lists and switches the route modes of v2 Control packages. Switches go through SetPackageRouteModesTx, the configuration path the identity cutover uses, so every rule of the configuration check holds and the package hosts pick the change up at their next configuration poll. Each switch records its revisions and an audit entry in the same transaction.
func (*RouteModeAdmin) List ¶ added in v4.1.0
func (a *RouteModeAdmin) List(ctx context.Context, packageID string, hosts map[string]map[string]RouteHostObservation) ([]PackageRouteModes, error)
List returns the route modes of every Control installation, or of packageID's. A package whose compatibility routes cannot be verified is listed with Error. hosts, when not nil, adds each host's report by package and route.
func (*RouteModeAdmin) Revisions ¶ added in v4.1.0
func (a *RouteModeAdmin) Revisions(ctx context.Context, packageID string, limit int) ([]model.RouteModeRevision, error)
Revisions returns the latest route-mode revisions, newest first, of packageID or of every package.
func (*RouteModeAdmin) Rollback ¶ added in v4.1.0
func (a *RouteModeAdmin) Rollback(ctx context.Context, packageID, reason string, actor RouteModeActor) (RouteModeResult, error)
Rollback returns every route of a package to legacy in one change, except identity group A, which only the identity rollback switches. It works on the effective modes: a route that runs natively only by default (no stored mode) gets an explicit legacy, so it stays legacy whatever the default policy becomes. It needs no confirmation; the reason is optional.
func (*RouteModeAdmin) Set ¶ added in v4.1.0
func (a *RouteModeAdmin) Set(ctx context.Context, request RouteModeChangeRequest, actor RouteModeActor) (RouteModeResult, error)
Set switches routes of a package to request.Mode. Named routes must all be allowed to switch, or nothing changes; without names every route that may switch to the mode does, and the others are reported as skipped. Switching to native needs request.Confirm and a reason.
type RouteModeChange ¶ added in v4.1.0
type RouteModeChange struct {
RouteID string `json:"route_id"`
From string `json:"from"`
To string `json:"to"`
}
RouteModeChange is one route's switch.
type RouteModeChangeRequest ¶ added in v4.1.0
type RouteModeChangeRequest struct {
PackageID string
Routes []string
Mode string
Reason string
// Confirm acknowledges a switch to native.
Confirm bool
}
RouteModeChangeRequest asks for routes of a package to switch to Mode. No Routes means every route of the package that may switch to Mode.
type RouteModeEntry ¶ added in v4.1.0
type RouteModeEntry struct {
RouteID string `json:"route_id"`
Method string `json:"method"`
Path string `json:"path"`
Transport string `json:"transport"`
// Catalog is the route's package extraction mode ("" when the
// extraction map does not list it).
Catalog string `json:"catalog"`
// Configured is the stored mode or, when the map does not name the
// route, the default policy's (native for a route of the rehearsed
// default set, legacy otherwise); Effective is what the kernel hands
// the host (ResolveEffectivePackageRouteModes), which differs only for
// identity group A. Stored is the raw stored mode ("" when none).
Configured string `json:"configured"`
Effective string `json:"effective"`
Stored string `json:"stored,omitempty"`
// Source is where the effective mode comes from: stored, default,
// kill-switch, package-too-old, identity-authority or unset.
Source string `json:"source"`
AllowedModes []string `json:"allowed_modes"`
Locked string `json:"locked"`
LockedReason string `json:"locked_reason"`
// Host is the running host's report, when there is one.
Host *RouteHostObservation `json:"host,omitempty"`
// MismatchSamples summarizes the stored shadow mismatch samples of the
// route (GET /api/v4/kernel/route-modes/mismatches), when there are
// any.
MismatchSamples *shadowsamples.Summary `json:"mismatch_samples,omitempty"`
}
RouteModeEntry is one compatibility route of a package and its modes.
type RouteModeResult ¶ added in v4.1.0
type RouteModeResult struct {
GroupID string `json:"group_id,omitempty"`
PackageID string `json:"package_id"`
Action string `json:"action"`
Mode string `json:"mode"`
ConfigRevision int64 `json:"config_revision"`
Changes []RouteModeChange `json:"changes"`
Skipped []RouteModeSkip `json:"skipped"`
}
RouteModeResult describes a committed change. A request that changes nothing has no GroupID and writes neither revisions nor an audit entry.
type RouteModeSkip ¶ added in v4.1.0
RouteModeSkip is a route a whole-package change left as it is.
type SecretDocumentOutcome ¶ added in v4.1.0
type SecretDocumentOutcome struct {
// Full is the document as stored in the legacy column: every secret
// in clear.
Full string
// Redacted is the document with the placeholder at every secret
// position: what administrators' answers show, and what a package
// stores in its own row.
Redacted string
// Kept counts the placeholders the incoming document sent, which keep
// their stored values; Cleared the stored secrets the incoming
// document no longer holds.
Kept int
Cleared int
}
SecretDocumentOutcome is what PutNodeProtocolSecretDocumentTx and PutNodeRawConfigDocumentTx stored.
func PutNodeProtocolSecretDocumentTx ¶ added in v4.1.0
func PutNodeProtocolSecretDocumentTx(tx *gorm.DB, protocolID uint, column, document string) (SecretDocumentOutcome, error)
PutNodeProtocolSecretDocumentTx stores one secret column of a node protocol: the incoming document, with the stored value at every position it sends as the placeholder (KeepNodeSecretsJSON), is written to the column and the split table (putNodeProtocolColumnsTx), as the protocol update does for the columns it carries.
func PutNodeRawConfigDocumentTx ¶ added in v4.1.0
func PutNodeRawConfigDocumentTx(tx *gorm.DB, nodeID uint, document string) (SecretDocumentOutcome, error)
PutNodeRawConfigDocumentTx stores a proxy node's raw configuration, as PutNodeProtocolSecretDocumentTx stores a protocol column.
type ServerService ¶
type ServerService struct {
// contains filtered or unexported fields
}
ServerService 服务器服务
func (*ServerService) BatchRecordTrafficLog ¶
func (s *ServerService) BatchRecordTrafficLog(serverType model.ServerType, serverID uint, traffics map[uint][2]int64, rate float64) error
BatchRecordTrafficLog 批量记录流量日志
func (*ServerService) BuildNodeConfig ¶
func (s *ServerService) BuildNodeConfig(serverType model.ServerType, serverID uint) (map[string]any, error)
BuildNodeConfig 构建节点配置
func (*ServerService) GetAllUsersOnlineCount ¶
func (s *ServerService) GetAllUsersOnlineCount() (map[string]int, error)
GetAllUsersOnlineCount 获取所有用户的在线IP数量
func (*ServerService) GetRoutesByIDs ¶
func (s *ServerService) GetRoutesByIDs(ids []uint) ([]model.ServerRoute, error)
GetRoutesByIDs 根据ID列表获取路由
func (*ServerService) GetServerByTypeAndID ¶
func (s *ServerService) GetServerByTypeAndID(serverType model.ServerType, serverID uint) (any, error)
GetServerByTypeAndID 根据类型和ID获取服务器
func (*ServerService) GetServerUsers ¶
func (s *ServerService) GetServerUsers(serverType model.ServerType, serverID uint) ([]model.User, error)
GetServerUsers 获取服务器可用用户列表
func (*ServerService) GetUserOnlineCount ¶
func (s *ServerService) GetUserOnlineCount(userID uint) (int64, error)
GetUserOnlineCount 获取用户在线IP数量(跨所有节点)
func (*ServerService) RecordAgentTrafficReport ¶ added in v4.1.0
func (s *ServerService) RecordAgentTrafficReport(nodeKind string, nodeID uint, batchID string, traffics map[uint][2]int64, rate float64) (bool, error)
RecordAgentTrafficReport applies a TrafficReport batch from the Agent Control stream (reports.v1) exactly as RecordNodeTrafficReport applies the legacy report of the same node, once per node and batch id: the batch record (internal/agentreports) is claimed in the transaction that applies the traffic. It reports whether this call applied the batch; false means a committed transaction applied it before, and nothing was counted again.
func (*ServerService) RecordNodeTrafficReport ¶
func (s *ServerService) RecordNodeTrafficReport(serverType model.ServerType, nodeID uint, traffics map[uint][2]int64, rate float64) error
RecordNodeTrafficReport atomically applies a node traffic report. Node clients retry a report when the panel returns an error, so logs, node counters, daily/monthly stats, and user counters must commit together.
func (*ServerService) RecordServerStat ¶
func (s *ServerService) RecordServerStat(serverType model.ServerType, serverID uint, upload, download int64, recordType string, recordAt int64) error
RecordServerStat 记录节点汇总统计,用于面板中的服务器统计表。 recordType: d=日统计, m=月统计。
func (*ServerService) RecordTrafficLog ¶
func (s *ServerService) RecordTrafficLog(serverType model.ServerType, serverID uint, userID uint, upload, download int64, rate float64) error
RecordTrafficLog 记录流量日志
func (*ServerService) UpdateOnlineStatus ¶
func (s *ServerService) UpdateOnlineStatus(serverType model.ServerType, serverID uint, userIPs map[uint][]string) error
UpdateOnlineStatus 更新用户在线状态
type SettingsAudit ¶ added in v4.1.0
type SettingsAudit int
SettingsAudit is the audit entry a write of the namespace records: the one the kernel's own handler records for the same change.
const ( // SettingsAuditNone records nothing. SettingsAuditNone SettingsAudit = iota // SettingsAuditSystemConfig records a system_config entry per key, as // the system configuration handlers do. SettingsAuditSystemConfig // SettingsAuditBackupConfig records a backup_config entry, as the // backup configuration handler does. SettingsAuditBackupConfig )
type SettingsAuditActor ¶ added in v4.1.0
SettingsAuditActor is who changed a setting, as the audit trail records it. The kernel's handlers take it from the request's context; the KernelSettings contract from the calling package's Actor.
type SettingsNamespace ¶ added in v4.1.0
type SettingsNamespace struct {
Name string
// Keys are exact keys; Prefixes match the longer keys that start with
// them.
Keys []string
Prefixes []string
Storage SettingsStorage
Audit SettingsAudit
// SecretKeys are secrets the kernel's key-name rule does not catch.
SecretKeys []string
}
SettingsNamespace is one entry of the kernel's namespace table.
func LookupSettingsNamespace ¶ added in v4.1.0
func LookupSettingsNamespace(name string) (SettingsNamespace, bool)
LookupSettingsNamespace returns the namespace called name.
func SettingsNamespaceOf ¶ added in v4.1.0
func SettingsNamespaceOf(key string) (SettingsNamespace, bool)
SettingsNamespaceOf returns the namespace key belongs to.
func SettingsNamespaces ¶ added in v4.1.0
func SettingsNamespaces() []SettingsNamespace
SettingsNamespaces returns the namespace table.
func (SettingsNamespace) Contains ¶ added in v4.1.0
func (n SettingsNamespace) Contains(key string) bool
Contains reports whether key belongs to the namespace.
func (SettingsNamespace) Secret ¶ added in v4.1.0
func (n SettingsNamespace) Secret(key string) bool
Secret reports whether key's value is a secret: a name the kernel masks for its administrators, or a key the namespace declares secret.
type SettingsStorage ¶ added in v4.1.0
type SettingsStorage int
SettingsStorage is where a namespace's keys live.
const ( // SettingsInSystemConfig keys are rows of v2_system_config. SettingsInSystemConfig SettingsStorage = iota // SettingsInBackupConfig keys are the fields of the first // v2_backup_config row. SettingsInBackupConfig )
type SpeedLimitInput ¶
type SpeedLimitService ¶
type SpeedLimitService struct {
// contains filtered or unexported fields
}
func NewSpeedLimitService ¶
func NewSpeedLimitService(db *gorm.DB) *SpeedLimitService
func (*SpeedLimitService) Create ¶
func (s *SpeedLimitService) Create(input SpeedLimitInput) (*model.SpeedLimit, error)
func (*SpeedLimitService) Delete ¶
func (s *SpeedLimitService) Delete(id uint) error
func (*SpeedLimitService) List ¶
func (s *SpeedLimitService) List() ([]model.SpeedLimit, error)
type SpeedLimitUpdateInput ¶
type SpeedLimitUpdateInput struct {
ID uint `json:"id"`
SpeedLimitInput
}
type StatsService ¶
type StatsService struct {
// contains filtered or unexported fields
}
StatsService 统计服务 (带缓存)
func NewStatsServiceOn ¶ added in v4.1.0
func NewStatsServiceOn(db *gorm.DB) *StatsService
NewStatsServiceOn returns a StatsService on db. The kernel contracts that answer the cached dashboard and subscription summaries (internal/kerneltelemetry, internal/kernelsubscriber) build one on their own database; the caches are the kernel's, shared with the legacy handlers whichever database handle reads them.
func (*StatsService) GetDashboardStats ¶
func (s *StatsService) GetDashboardStats(forceRefresh bool) (*DashboardStats, error)
GetDashboardStats 获取仪表盘统计 (优先从缓存读取)
func (*StatsService) GetHourlyTraffic ¶
func (s *StatsService) GetHourlyTraffic(hours int, userID uint) ([]HourlyTraffic, error)
GetHourlyTraffic 返回最近 hours 个整点小时的流量序列 (含当前未结束的小时), 数据源为 v2_server_log, 按 (log_at/3600) 分桶聚合 SUM((u+d)*rate)。 userID > 0 时只统计该用户的流量; userID == 0 时统计全局。 缺失的小时补零, 结果按时间升序返回, 便于前端直接绘制折线图。
func (*StatsService) GetNodeTraffic ¶ added in v4.2.0
func (s *StatsService) GetNodeTraffic(nodeID uint, granularity string, since, until time.Time) (*NodeTrafficSeries, error)
GetNodeTraffic returns one node's traffic series between since and until (see NodeTrafficBucketBounds for how they are aligned and bounded).
Hourly buckets sum the node's rows of v2_server_log, (u * rate) up and (d * rate) down, over every server type the node reported under (agent and legacy reports write "node", UniProxy the protocol name; the node id is the same). It reads the rows of one node in the window through idx_v2_server_log_server_id and idx_v2_server_log_log_at: cheaper than the global GetHourlyTraffic, which scans the window of every node, and bounded by the retention of the raw log (docs/reference/traffic-stats-operations.md). Daily buckets are the node's v2_stat_server day rows, which are kept and small, and are recorded with the rate applied already.
ErrNodeTrafficNode when the node does not exist.
func (*StatsService) GetTrafficLogMeta ¶
func (s *StatsService) GetTrafficLogMeta(userID uint) (TrafficLogMeta, error)
GetTrafficLogMeta returns lightweight diagnostics for traffic chart pages.
func (*StatsService) GetUserSubscription ¶
func (s *StatsService) GetUserSubscription(userID uint, forceRefresh bool) (*UserSubscription, error)
GetUserSubscription 获取用户订阅详情 (优先从缓存读取)
func (*StatsService) GetUserTrafficRanking ¶
func (s *StatsService) GetUserTrafficRanking(hours int, limit int, includeZeroUsers bool) ([]UserTrafficRank, error)
GetUserTrafficRanking 返回最近 hours 小时内按用户聚合的流量排行 (倒序), 数据源为 v2_server_log, 关联 v2_user 取 email。limit 限制返回条数。 includeZeroUsers 为 true 时从用户表出发返回无区间流量的用户, 便于后台按任意用户筛选小时图。
func (*StatsService) UserSubscriptionSummary ¶ added in v4.1.0
func (s *StatsService) UserSubscriptionSummary(userID uint, forceRefresh bool, configService *SystemConfigService, cfg *config.Config) (*UserSubscription, error)
UserSubscriptionSummary is the answer of GET /api/v2/user/subscription: the user's cached summary (GetUserSubscription) with the subscription link settings, which are read on every call and not cached. It answers a copy, so the cached entry, which the user dashboard answers too, never carries the link settings and no request writes to it.
type SubscriberEntitlements ¶ added in v4.1.0
type SubscriberEntitlements struct {
Balance *int64 `json:"balance"`
PlanID *uint `json:"plan_id"`
GroupID *uint `json:"group_id"`
ExpiredAt *int64 `json:"expired_at"`
TransferEnable *int64 `json:"transfer_enable"`
SpeedLimit *int64 `json:"speed_limit"`
DeviceLimit *int `json:"device_limit"`
FlowResetTime *int64 `json:"flowResetTime"`
RemarkContent *string `json:"remark_content"`
}
SubscriberEntitlements are the v2_user fields an administrator edits besides the identity fields. The JSON keys are those of the v2 admin user update request; an absent or null field is left unchanged.
func (SubscriberEntitlements) Updates ¶ added in v4.1.0
func (e SubscriberEntitlements) Updates(plans *PlanService) map[string]any
Updates returns the v2_user column updates. A new plan also sets the group and, unless given explicitly, the traffic and limits from the plan, as the v2 admin API does.
type SubscriptionService ¶
type SubscriptionService struct {
// contains filtered or unexported fields
}
SubscriptionService 订阅服务
func NewSubscriptionService ¶
func NewSubscriptionService() *SubscriptionService
NewSubscriptionService 创建订阅服务
func (*SubscriptionService) AssignGroupToPlan ¶
func (s *SubscriptionService) AssignGroupToPlan(planID, groupID uint) error
AssignGroupToPlan 为套餐分配订阅分组
func (*SubscriptionService) AssignGroupToUser ¶
func (s *SubscriptionService) AssignGroupToUser(userID, groupID uint, expireAt *int64, transferEnable *int64, nextRenewPrice *int64, requestID string) error
AssignGroupToUser 为用户分配订阅分组: the membership is created, or the given fields of an existing one are set, through the subscriber engine (subscriber.GrantSubscriptionGroupTx) once per requestID (SubscriptionGroupGrantRequestID), as the subscription package's native route does through KernelSubscriber. An empty requestID applies every time.
func (*SubscriptionService) BuildWireGuardRuntimeUserExtras ¶
func (s *SubscriptionService) BuildWireGuardRuntimeUserExtras(protocol *model.NodeProtocol, users []*model.User) (map[uint]map[string]string, error)
func (*SubscriptionService) CreateGroup ¶
func (s *SubscriptionService) CreateGroup(group *model.SubscriptionGroup) error
CreateGroup 创建订阅分组, its own columns only.
Group and template writes take the model an administrator's body was bound to, and GORM saves the associations of a model it writes. A group body's "protocols" upserted v2_node_protocol rows, and the nodes nested in them into v2_node (without an API key and without the node routes' checks), and linked them to the group; its "templates" created templates or moved existing ones into the group; a template body's "group" created a group and overrode the group the route names. Those belong to their own routes: the associations of a body are dropped and never saved.
func (*SubscriptionService) CreateTemplate ¶
func (s *SubscriptionService) CreateTemplate(template *model.SubscriptionTemplate) error
CreateTemplate 创建订阅模板, its own columns only (see CreateGroup): the template stays in the group its route names.
func (*SubscriptionService) DeleteGroup ¶
func (s *SubscriptionService) DeleteGroup(id uint, requestID string) error
DeleteGroup 删除订阅分组. Its members' memberships go through the subscriber engine (subscriber.RemoveSubscriptionGroupMembersTx), with requestID (SubscriptionGroupDeleteRequestID) in the subscriber request ledger and a change for each active member, as the subscription package's native route does through KernelSubscriber.
func (*SubscriptionService) DeleteTemplate ¶
func (s *SubscriptionService) DeleteTemplate(id uint) error
DeleteTemplate 删除订阅模板
func (*SubscriptionService) GetGroup ¶
func (s *SubscriptionService) GetGroup(id uint) (*model.SubscriptionGroup, error)
GetGroup 获取订阅分组
func (*SubscriptionService) GetGroupStats ¶
func (s *SubscriptionService) GetGroupStats() ([]GroupStats, error)
GetGroupStats 获取所有订阅分组的统计数据
func (*SubscriptionService) GetGroups ¶
func (s *SubscriptionService) GetGroups() ([]*model.SubscriptionGroup, error)
GetGroups 获取所有订阅分组
func (*SubscriptionService) GetOrCreateWireGuardPeer ¶
func (s *SubscriptionService) GetOrCreateWireGuardPeer(protocolID, userID uint, cidr string) (*model.WireGuardPeer, error)
func (*SubscriptionService) GetPlanGroups ¶
func (s *SubscriptionService) GetPlanGroups(planID uint) ([]*model.SubscriptionGroup, error)
GetPlanGroups 获取套餐的订阅分组
func (*SubscriptionService) GetTemplate ¶
func (s *SubscriptionService) GetTemplate(id uint) (*model.SubscriptionTemplate, error)
GetTemplate 获取订阅模板
func (*SubscriptionService) GetTemplatesByGroup ¶
func (s *SubscriptionService) GetTemplatesByGroup(groupID uint) ([]*model.SubscriptionTemplate, error)
GetTemplatesByGroup 获取分组的模板
func (*SubscriptionService) GetUserGroups ¶
func (s *SubscriptionService) GetUserGroups(userID uint) ([]*model.SubscriptionGroup, error)
GetUserGroups 获取用户的订阅分组
func (*SubscriptionService) GetUserSubscription ¶
func (s *SubscriptionService) GetUserSubscription(req *model.SubscriptionRequest) (*model.SubscriptionResponse, error)
GetUserSubscription 获取用户订阅 token: 用户 token format: 订阅格式 groups: 指定分组 (可选) include: 包含关键词 exclude: 排除关键词
func (*SubscriptionService) ListGroupMembers ¶ added in v4.2.0
func (s *SubscriptionService) ListGroupMembers(groupID uint, params GroupMembersParams) (*GroupMembersResult, error)
ListGroupMembers lists a subscription group's direct members, newest grant first (members granted in the same instant by id, newest first), so pages neither repeat nor skip one. An unknown group is ErrSubscriptionGroupNotFound.
func (*SubscriptionService) RemoveGroupFromPlan ¶
func (s *SubscriptionService) RemoveGroupFromPlan(planID, groupID uint) error
RemoveGroupFromPlan 移除套餐的订阅分组
func (*SubscriptionService) RemoveGroupFromUser ¶
func (s *SubscriptionService) RemoveGroupFromUser(userID, groupID uint, requestID string) error
RemoveGroupFromUser 移除用户的订阅分组, through the subscriber engine (subscriber.RevokeSubscriptionGroupTx) once per requestID (SubscriptionGroupRevokeRequestID).
func (*SubscriptionService) UpdateGroup ¶
func (s *SubscriptionService) UpdateGroup(group *model.SubscriptionGroup) error
UpdateGroup 更新订阅分组, its own columns only (see CreateGroup).
func (*SubscriptionService) UpdateTemplateFields ¶
func (s *SubscriptionService) UpdateTemplateFields(id uint, fields map[string]any) error
UpdateTemplateFields 按字段局部更新订阅模板
type SubscriptionSettings ¶
type SubscriptionSettings struct {
SubscribePath string `json:"subscribe_path"`
SubscribeDomains []string `json:"subscribe_domains"`
}
func GetSubscriptionSettings ¶
func GetSubscriptionSettings(configService *SystemConfigService, cfg *config.Config) SubscriptionSettings
type SystemConfigService ¶
type SystemConfigService struct {
// contains filtered or unexported fields
}
func NewSystemConfigService ¶
func NewSystemConfigService(db *gorm.DB) *SystemConfigService
func (*SystemConfigService) Delete ¶
func (s *SystemConfigService) Delete(key string) error
func (*SystemConfigService) GetAll ¶
func (s *SystemConfigService) GetAll() ([]model.SystemConfig, error)
func (*SystemConfigService) GetAsMap ¶
func (s *SystemConfigService) GetAsMap() (map[string]string, error)
func (*SystemConfigService) GetByGroup ¶
func (s *SystemConfigService) GetByGroup(group string) ([]model.SystemConfig, error)
func (*SystemConfigService) GetEntry ¶
func (s *SystemConfigService) GetEntry(key string) (*model.SystemConfig, error)
func (*SystemConfigService) GetJSON ¶
func (s *SystemConfigService) GetJSON(key string, v any) error
func (*SystemConfigService) Set ¶
func (s *SystemConfigService) Set(key, value, cfgType, group, remark string) error
type TOTPSetup ¶
type TOTPSetup struct {
Secret string `json:"secret"` // 密钥 (base32)
URL string `json:"url"` // otpauth:// URL
QRCode string `json:"qr_code"` // 用于生成二维码
BackupCodes []string `json:"backup_codes"` // 备用码
}
TOTPSetup TOTP设置结果
type TargetCatalogItem ¶
type TargetCatalogItem struct {
TargetKey string `json:"targetKey"`
TargetType string `json:"targetType"`
TargetID uint `json:"targetId"`
Label string `json:"label"`
Host string `json:"host"`
Port int `json:"port"`
LatestBucketAt int64 `json:"latestBucketAt"`
LatestAvgRTT float64 `json:"latestAvgRtt"`
LatestLoss float64 `json:"latestLoss"`
Online bool `json:"online"`
}
type TelegramBotService ¶
type TelegramBotService struct {
// contains filtered or unexported fields
}
TelegramBotService Telegram Bot服务
func NewTelegramBotService ¶
func NewTelegramBotService(db *gorm.DB) *TelegramBotService
NewTelegramBotService 创建服务
func (*TelegramBotService) BindUser ¶
func (s *TelegramBotService) BindUser(telegramID int64, email string, from *TelegramUser) error
BindUser 绑定用户
func (*TelegramBotService) Broadcast ¶
func (s *TelegramBotService) Broadcast(text string) error
Broadcast 广播消息
func (*TelegramBotService) DeleteWebhook ¶
func (s *TelegramBotService) DeleteWebhook() error
DeleteWebhook 删除Webhook
func (*TelegramBotService) GetBot ¶
func (s *TelegramBotService) GetBot() (*model.TelegramBot, error)
GetBot 获取Bot配置
func (*TelegramBotService) GetTelegramUserService ¶
func (s *TelegramBotService) GetTelegramUserService() *TelegramUserService
GetTelegramUserService 获取Telegram用户服务
func (*TelegramBotService) HandleUpdate ¶
func (s *TelegramBotService) HandleUpdate(update *TelegramUpdate) error
HandleUpdate 处理Webhook更新
func (*TelegramBotService) ProbeSend ¶ added in v4.2.0
func (s *TelegramBotService) ProbeSend(ctx context.Context, bot *model.TelegramBot, chatID int64, text string) TelegramProbeResult
ProbeSend sends text to chatID with bot's token and classifies the answer. It follows no redirect and gives up after ten seconds or when ctx ends. bot may be nil (no bot row).
func (*TelegramBotService) SendMessage ¶
func (s *TelegramBotService) SendMessage(chatID int64, text string) error
SendMessage 发送消息
func (*TelegramBotService) SendNotification ¶
func (s *TelegramBotService) SendNotification(telegramID int64, title, content string) error
SendNotification 发送通知
func (*TelegramBotService) SetAPIBase ¶ added in v4.2.0
func (s *TelegramBotService) SetAPIBase(base string)
SetAPIBase points the service's probe at another Bot API endpoint. It is for tests; the address comes from code, never from a request.
func (*TelegramBotService) SetWebhook ¶
func (s *TelegramBotService) SetWebhook(webhookURL string) error
SetWebhook 设置Webhook
func (*TelegramBotService) UpdateBot ¶
func (s *TelegramBotService) UpdateBot(bot *model.TelegramBot) error
UpdateBot 更新Bot配置
func (*TelegramBotService) ValidWebhookSecret ¶ added in v4.2.1
func (s *TelegramBotService) ValidWebhookSecret(header string) bool
ValidWebhookSecret reports whether an update carries the secret registered for the current bot token. With no bot configured nothing is valid.
type TelegramCallback ¶
type TelegramCallback struct {
ID string `json:"id"`
From TelegramUser `json:"from"`
Message TelegramMessage `json:"message"`
Data string `json:"data"`
}
TelegramCallback Telegram回调
type TelegramChat ¶
type TelegramChat struct {
ID int64 `json:"id"`
Type string `json:"type"`
Title string `json:"title,omitempty"`
Username string `json:"username,omitempty"`
}
TelegramChat Telegram聊天
type TelegramMessage ¶
type TelegramMessage struct {
MessageID int64 `json:"message_id"`
From *TelegramUser `json:"from,omitempty"`
Chat TelegramChat `json:"chat"`
Date int64 `json:"date"`
Text string `json:"text,omitempty"`
}
TelegramMessage Telegram消息
type TelegramProbeClass ¶ added in v4.2.0
type TelegramProbeClass string
TelegramProbeClass is the outcome class of a probe.
const ( // TelegramProbeOK: Telegram accepted the message. TelegramProbeOK TelegramProbeClass = "ok" // TelegramProbeInvalidToken: the token is malformed or Telegram refused it // (401 Unauthorized, or 404 Not Found on the bot path). TelegramProbeInvalidToken TelegramProbeClass = "invalid_token" // TelegramProbeChatNotFound: the chat does not exist for this bot. TelegramProbeChatNotFound TelegramProbeClass = "chat_not_found" // TelegramProbeBotBlocked: Telegram answered 403, for example the user // blocked the bot or never started it. TelegramProbeBotBlocked TelegramProbeClass = "bot_blocked" // TelegramProbeRateLimited: Telegram answered 429. TelegramProbeRateLimited TelegramProbeClass = "rate_limited" // TelegramProbeNotConfigured: there is no bot row or it holds no token. TelegramProbeNotConfigured TelegramProbeClass = "not_configured" // TelegramProbeNetworkError: Telegram could not be reached (see Reason). TelegramProbeNetworkError TelegramProbeClass = "network_error" // TelegramProbeUnknown: any other answer. TelegramProbeUnknown TelegramProbeClass = "unknown" )
The classes a probe answers.
type TelegramProbeResult ¶ added in v4.2.0
type TelegramProbeResult struct {
Class TelegramProbeClass `json:"class"`
// ErrorCode is the Bot API's error_code (else the HTTP status) of a
// refusal; 0 when there was none.
ErrorCode int `json:"error_code,omitempty"`
// Reason refines a network_error.
Reason string `json:"reason,omitempty"`
}
TelegramProbeResult is the classified outcome of a probe. It holds no token, no URL and no text from Telegram or from a Go error.
func (TelegramProbeResult) Message ¶ added in v4.2.0
func (r TelegramProbeResult) Message() string
Message is a fixed sentence per class.
func (TelegramProbeResult) OK ¶ added in v4.2.0
func (r TelegramProbeResult) OK() bool
OK reports whether Telegram accepted the message.
type TelegramUpdate ¶
type TelegramUpdate struct {
UpdateID int64 `json:"update_id"`
Message *TelegramMessage `json:"message,omitempty"`
CallbackQuery *TelegramCallback `json:"callback_query,omitempty"`
}
TelegramUpdate Telegram更新
type TelegramUser ¶
type TelegramUser struct {
ID int64 `json:"id"`
IsBot bool `json:"is_bot"`
FirstName string `json:"first_name"`
LastName string `json:"last_name,omitempty"`
Username string `json:"username,omitempty"`
LanguageCode string `json:"language_code,omitempty"`
}
TelegramUser Telegram用户
type TelegramUserService ¶
type TelegramUserService struct {
// contains filtered or unexported fields
}
TelegramUserService Telegram用户服务
func NewTelegramUserService ¶
func NewTelegramUserService(db *gorm.DB) *TelegramUserService
NewTelegramUserService 创建服务
func (*TelegramUserService) GetByUserID ¶
func (s *TelegramUserService) GetByUserID(userID uint) (*model.TelegramUser, error)
GetByUserID 根据系统用户ID获取绑定
type Topology ¶
type Topology struct {
Nodes []TopologyNode `json:"nodes"`
Edges []TopologyEdge `json:"edges"`
}
type TopologyDeploymentDiagnosticIssue ¶
type TopologyDeploymentDiagnosticIssue struct {
Code string `json:"code"`
Path string `json:"path"`
Message string `json:"message"`
Severity string `json:"severity"`
}
TopologyDeploymentDiagnosticIssue is stable, machine-readable preflight output. Code and path intentionally mirror ValidateTopology where possible so the editor can point at the same field that the planner would reject.
type TopologyDeploymentEvent ¶
type TopologyDeploymentEvent struct {
Type string `json:"type"`
At time.Time `json:"at"`
OperationID string `json:"operation_id,omitempty"`
StepID *uint `json:"step_id,omitempty"`
NodeID *uint `json:"node_id,omitempty"`
PluginID string `json:"plugin_id,omitempty"`
State string `json:"state"`
HasError bool `json:"has_error"`
// Message is a stable kernel-generated lifecycle summary. It is never a
// persisted deployment, observed-state, or Agent error.
Message string `json:"message,omitempty"`
}
func PublicTopologyDeploymentEvent ¶
func PublicTopologyDeploymentEvent(event TopologyDeploymentEvent) TopologyDeploymentEvent
PublicTopologyDeploymentEvent never trusts a pre-existing Message field: callers only receive a summary regenerated from the event type and state.
type TopologyDeploymentExecutor ¶
type TopologyDeploymentExecutor struct {
// contains filtered or unexported fields
}
TopologyDeploymentExecutor turns a previously planned revision into durable Agent operations. It never opens a network/data-plane connection itself; the existing KernelOperationBridge remains the sole Agent transport.
A failed operation fences further expansion immediately, cancels in-flight sibling work, then compensates successful/started steps in reverse DAG order. The compensation restores the previous active revision where possible, or disables a newly introduced plugin vertex when no predecessor exists.
func NewTopologyDeploymentExecutor ¶
func NewTopologyDeploymentExecutor(db *gorm.DB) (*TopologyDeploymentExecutor, error)
func (*TopologyDeploymentExecutor) Run ¶ added in v4.1.0
func (e *TopologyDeploymentExecutor) Run(ctx context.Context, interval time.Duration, reportError func(error))
Run reconciles every interval and blocks until ctx is cancelled. It is deliberately separate from plan/apply HTTP paths so topology execution remains opt-in. ctx must not be nil.
func (*TopologyDeploymentExecutor) RunOnce ¶
func (e *TopologyDeploymentExecutor) RunOnce(ctx context.Context) (int, error)
RunOnce reconciles every active topology deployment. Operations are created in database transactions and carry stable idempotency keys, so repeating a pass after a Control restart is safe.
type TopologyDeploymentOperation ¶
type TopologyDeploymentOperation struct {
OperationID string `json:"operation_id"`
StepID *uint `json:"step_id,omitempty"`
NodeID *uint `json:"node_id,omitempty"`
PluginID string `json:"plugin_id"`
TargetVersion string `json:"target_version"`
Kind string `json:"kind"`
Revision int64 `json:"revision"`
State string `json:"state"`
Attempt int `json:"attempt"`
DeadlineAt *time.Time `json:"deadline_at,omitempty"`
DispatchedAt *time.Time `json:"dispatched_at,omitempty"`
ObservedAt *time.Time `json:"observed_at,omitempty"`
HasError bool `json:"has_error"`
LastError string `json:"last_error,omitempty"`
UpdatedAt time.Time `json:"updated_at"`
}
TopologyDeploymentOperation is the safe, linkage-focused projection used by deployment status. ConfigJSON, ResultJSON, and raw Agent errors are intentionally omitted. LastError is a stable kernel-generated summary, not the persisted operation error.
func PublicTopologyDeploymentOperation ¶
func PublicTopologyDeploymentOperation(operation TopologyDeploymentOperation) TopologyDeploymentOperation
PublicTopologyDeploymentOperation defensively regenerates the error summary even though the timeline loader already does so. This keeps the HTTP view safe if an in-process caller constructs a TopologyDeploymentStatus manually.
type TopologyDeploymentPlanInput ¶
type TopologyDeploymentPlanInput struct {
TopologyID uint
RevisionID uint
ActorID uint
RolloutGroup string
FailurePolicy string
}
TopologyDeploymentPlanInput identifies an immutable topology revision to compile into a durable node-operation plan. The plan is intentionally inert: callers must request apply and the separately feature-gated executor must be running before any Agent operation is created.
type TopologyDeploymentPreview ¶
type TopologyDeploymentPreview struct {
TopologyID uint `json:"topology_id"`
RevisionID uint `json:"revision_id"`
PreviousRevisionID *uint `json:"previous_revision_id,omitempty"`
RolloutGroup string `json:"rollout_group,omitempty"`
FailurePolicy string `json:"failure_policy"`
Valid bool `json:"valid"`
Issues []TopologyDeploymentDiagnosticIssue `json:"issues"`
Checks []TopologyDeploymentDiagnosticCheck `json:"checks"`
Steps []TopologyDeploymentPreviewStep `json:"steps"`
}
func PreviewTopologyDeployment ¶
func PreviewTopologyDeployment(db *gorm.DB, input TopologyDeploymentPreviewInput) (*TopologyDeploymentPreview, error)
PreviewTopologyDeployment performs all checks that are safe to perform before PlanTopologyDeployment. It intentionally does not call the planner, since the planner persists a deployment row by design.
type TopologyDeploymentPreviewInput ¶
type TopologyDeploymentPreviewInput struct {
TopologyID uint `json:"topology_id"`
RevisionID uint `json:"revision_id"`
RolloutGroup string `json:"rollout_group"`
FailurePolicy string `json:"failure_policy"`
}
TopologyDeploymentPreviewInput identifies a revision and the optional rollout slice to inspect. Preview is deliberately read-only: it never creates a deployment, operation, or observed-state row.
type TopologyDeploymentPreviewStep ¶
type TopologyDeploymentPreviewStep struct {
Order int `json:"order"`
VertexID uint `json:"vertex_id"`
VertexKey string `json:"vertex_key"`
NodeID uint `json:"node_id"`
PluginID string `json:"plugin_id"`
Role string `json:"role"`
TargetVersion string `json:"target_version"`
Removal bool `json:"removal"`
ApplyAction string `json:"apply_action"`
RollbackMode string `json:"rollback_mode"`
Dependencies []string `json:"dependencies,omitempty"`
Operations []string `json:"operations"`
ConfigHash string `json:"config_hash,omitempty"`
}
TopologyDeploymentPreviewStep describes the durable operations that a real plan would create. Operation IDs are intentionally absent because preview must not reserve identities or mutate the operation stream.
type TopologyDeploymentStatus ¶
type TopologyDeploymentStatus struct {
Deployment model.TopologyDeployment `json:"deployment"`
Steps []model.TopologyDeploymentStep `json:"steps"`
Observed []model.TopologyObservedState `json:"observed_states"`
Operations []TopologyDeploymentOperation `json:"operations"`
Events []TopologyDeploymentEvent `json:"events"`
}
TopologyDeploymentStatus is the transport-neutral status read used by the HTTP handler and tests. All fields are persisted kernel records.
func GetTopologyDeploymentStatus ¶
func GetTopologyDeploymentStatus(db *gorm.DB, deploymentID uint) (*TopologyDeploymentStatus, error)
type TopologyDeploymentStatusView ¶
type TopologyDeploymentStatusView struct {
Deployment TopologyDeploymentView `json:"deployment"`
Steps []TopologyDeploymentStepView `json:"steps"`
Observed []TopologyObservedStateView `json:"observed_states"`
Operations []TopologyDeploymentOperation `json:"operations"`
Events []TopologyDeploymentEvent `json:"events"`
}
TopologyDeploymentStatusView is the only topology deployment status shape intended for HTTP clients. It deliberately leaves configuration documents, rollback documents, Agent result documents, Agent health documents, and raw persisted errors on the kernel side of the boundary.
func PublicTopologyDeploymentStatus ¶
func PublicTopologyDeploymentStatus(status TopologyDeploymentStatus) TopologyDeploymentStatusView
PublicTopologyDeploymentStatus projects an internal status read to its explicit public representation. Do not return TopologyDeploymentStatus from an HTTP handler: it contains persistence models with secret-bearing fields.
type TopologyDeploymentStepView ¶
type TopologyDeploymentStepView struct {
ID uint `json:"id"`
DeploymentID uint `json:"deployment_id"`
VertexID uint `json:"vertex_id"`
VertexKey string `json:"vertex_key"`
NodeID uint `json:"node_id"`
PluginID string `json:"plugin_id"`
Role string `json:"role"`
TargetVersion string `json:"target_version"`
ApplyOrder int `json:"apply_order"`
Removal bool `json:"removal"`
ApplyAction string `json:"apply_action"`
RollbackMode string `json:"rollback_mode"`
State string `json:"state"`
HasError bool `json:"has_error"`
LastError string `json:"last_error,omitempty"`
ConfigureOperationID string `json:"configure_operation_id,omitempty"`
EnableOperationID string `json:"enable_operation_id,omitempty"`
DisableOperationID string `json:"disable_operation_id,omitempty"`
RollbackConfigureOperationID string `json:"rollback_configure_operation_id,omitempty"`
RollbackEnableOperationID string `json:"rollback_enable_operation_id,omitempty"`
RollbackDisableOperationID string `json:"rollback_disable_operation_id,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
TopologyDeploymentStepView is a state-only projection. The active and rollback configuration documents remain write-only kernel records.
func PublicTopologyDeploymentStep ¶
func PublicTopologyDeploymentStep(step model.TopologyDeploymentStep) TopologyDeploymentStepView
type TopologyDeploymentView ¶
type TopologyDeploymentView struct {
ID uint `json:"id"`
TopologyID uint `json:"topology_id"`
RevisionID uint `json:"revision_id"`
PreviousRevisionID *uint `json:"previous_revision_id,omitempty"`
RolloutGroup string `json:"rollout_group"`
State string `json:"state"`
FailurePolicy string `json:"failure_policy"`
HasError bool `json:"has_error"`
LastError string `json:"last_error,omitempty"`
HealthGateDeadlineAt *time.Time `json:"health_gate_deadline_at,omitempty"`
RollbackStartedAt *time.Time `json:"rollback_started_at,omitempty"`
RollbackCompletedAt *time.Time `json:"rollback_completed_at,omitempty"`
CreatedBy uint `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
}
TopologyDeploymentView is a status-only projection of a durable deployment. LastError is a stable summary derived from state, never the persisted value.
func PublicTopologyDeployment ¶
func PublicTopologyDeployment(deployment model.TopologyDeployment) TopologyDeploymentView
type TopologyEdge ¶
type TopologyNode ¶
type TopologyNode struct {
ID string `json:"id"` // "node-<id>"
Label string `json:"label"`
Kind string `json:"kind"` // relay | exit
Region string `json:"region"`
Online bool `json:"online"`
Status int `json:"status"`
LatencyMs int `json:"latencyMs"`
Load float64 `json:"load"`
CurrentConn int `json:"currentConn"`
Weight int `json:"weight"`
}
type TopologyObservedStateUpdate ¶
type TopologyObservedStateUpdate struct {
DeploymentID uint
NodeID uint
DesiredRevision int64
ObservedRevision int64
State string
HealthJSON string
LastError string
ObservedAt time.Time
}
TopologyObservedStateUpdate is the transport-neutral observed-state write contract used by the Agent bridge and the future topology executor.
type TopologyObservedStateView ¶
type TopologyObservedStateView struct {
ID uint `json:"id"`
DeploymentID uint `json:"deployment_id"`
NodeID uint `json:"node_id"`
DesiredRevision int64 `json:"desired_revision"`
ObservedRevision int64 `json:"observed_revision"`
State string `json:"state"`
HealthReported bool `json:"health_reported"`
HasError bool `json:"has_error"`
LastError string `json:"last_error,omitempty"`
UpdatedAt time.Time `json:"updated_at"`
}
TopologyObservedStateView contains only monotonic state metadata. Health is represented by a presence bit because plugin-provided health JSON is not a stable or safe API contract.
func PublicTopologyObservedState ¶
func PublicTopologyObservedState(observed model.TopologyObservedState) TopologyObservedStateView
func PublicTopologyObservedStates ¶
func PublicTopologyObservedStates(rows []model.TopologyObservedState) []TopologyObservedStateView
type TopologyRevisionInput ¶
type TopologyRevisionInput struct {
Message string `json:"message"`
Vertices []model.TopologyVertex `json:"vertices"`
Edges []model.TopologyEdge `json:"edges"`
}
type TopologyValidationIssue ¶
type TopologyValidationIssue struct {
Code string `json:"code"`
Path string `json:"path"`
Message string `json:"message"`
}
func ValidateTopology ¶
func ValidateTopology(input TopologyRevisionInput) []TopologyValidationIssue
func ValidateTopologyAssignments ¶
func ValidateTopologyAssignments(db *gorm.DB, scopeID string, input TopologyRevisionInput) []TopologyValidationIssue
ValidateTopologyAssignments verifies that a plugin instance placed on a physical node has a matching enabled service assignment in the topology's scope. It deliberately does not inspect runtime Agent capabilities yet: those are observed by the Supervisor phase, while assignments remain the control-plane source of truth.
type TrafficLogMeta ¶
type TrafficLogMeta struct {
LatestLogAt int64 `json:"latest_log_at"` // 最近一次流量上报 Unix 秒, 0 表示从未上报
}
type TunnelDiagnosisReport ¶
type TunnelDiagnosisReport struct {
TunnelID uint `json:"tunnelId"`
TunnelName string `json:"tunnelName"`
TunnelType string `json:"tunnelType"`
Timestamp int64 `json:"timestamp"`
Results []DiagnosisOutcome `json:"results"`
}
type UserListItem ¶ added in v4.1.0
type UserListItem struct {
ID uint `json:"id"`
Email string `json:"email"`
Balance int64 `json:"balance"`
CommissionBalance int64 `json:"commission_balance"`
DeviceLimit *int `json:"device_limit"`
SpeedLimit *int64 `json:"speed_limit"`
FlowResetTime int64 `json:"flowResetTime"`
TransferEnable int64 `json:"transfer_enable"`
U int64 `json:"u"`
D int64 `json:"d"`
PlanID *uint `json:"plan_id"`
GroupID *uint `json:"group_id"`
ExpiredAt *int64 `json:"expired_at"`
Banned int `json:"banned"`
IsAdmin int `json:"is_admin"`
IsStaff int `json:"is_staff"`
CreatedAt time.Time `json:"created_at"`
// Plan is never loaded with the row.
Plan *UserListPlan `gorm:"-" json:"plan,omitempty"`
}
UserListItem is one user in the administrator's list: the account (e-mail, administrator, staff and ban flags), the subscription summary (plan, group, traffic, limits, reset day, expiry, balances) and the plan's id and name: the columns of kapi_user_directory_v1, kapi_subscriber_entitlement_v1 and kapi_plan_name_v1. A plan that no longer exists is left out. It carries no credential: the subscription token and proxy uuid, and the rest of the row, are read one user at a time from GET /api/v2/admin/users/:id. identity-platform's native list answers the same fields (packages/identity-platform/native/directory.go).
type UserListParams ¶
type UserListParams struct {
Page int
PageSize int
Email string
PlanID *uint
Status string // all, active, expired, banned
// OrderBy is an ORDER BY clause from v2compat.ParseListSort over
// UserSortColumns, never request text; empty keeps the default order.
OrderBy string
}
UserListParams 用户列表查询参数
type UserListPlan ¶ added in v4.1.0
UserListPlan names a listed user's plan: its id and name, never the rest of the plan row.
type UserListResult ¶
type UserListResult struct {
Total int64 `json:"total"`
List []UserListItem `json:"list"`
}
UserListResult 用户列表结果
type UserService ¶
type UserService struct {
// contains filtered or unexported fields
}
UserService 用户服务
func NewUserServiceFor ¶ added in v4.2.0
func NewUserServiceFor(db *gorm.DB) *UserService
NewUserServiceFor creates a user service over db instead of the process database: for callers that already hold their handle.
func (*UserService) BatchUpdateTraffic ¶
func (s *UserService) BatchUpdateTraffic(traffics map[uint][2]int64) error
BatchUpdateTraffic 批量更新用户流量
func (*UserService) GetActiveUsers ¶
func (s *UserService) GetActiveUsers() ([]model.User, error)
GetActiveUsers 获取所有有效用户
func (*UserService) GetActiveUsersByGroupID ¶
func (s *UserService) GetActiveUsersByGroupID(groupID uint) ([]model.User, error)
GetActiveUsersByGroupID 获取指定分组的有效用户
func (*UserService) GetActiveUsersForNode ¶
func (s *UserService) GetActiveUsersForNode(groupID *uint) ([]*model.User, error)
GetActiveUsersForNode 获取节点可用的有效用户 groupID 为 nil 时返回所有有效用户,否则返回指定分组的用户
func (*UserService) GetByEmail ¶
func (s *UserService) GetByEmail(email string) (*model.User, error)
GetByEmail 根据Email获取用户
func (*UserService) GetByID ¶
func (s *UserService) GetByID(id uint) (*model.User, error)
GetByID 根据ID获取用户
func (*UserService) GetByToken ¶
func (s *UserService) GetByToken(token string) (*model.User, error)
GetByToken 根据Token获取用户
func (*UserService) GetByUUID ¶
func (s *UserService) GetByUUID(uuid string) (*model.User, error)
GetByUUID 根据UUID获取用户
func (*UserService) GetList ¶
func (s *UserService) GetList(params UserListParams) (*UserListResult, error)
GetList 获取用户列表. Users created in the same instant keep a stable order (created_at DESC, id DESC), so pages neither repeat nor skip a user.
func (*UserService) GetStats ¶
func (s *UserService) GetStats() (map[string]any, error)
GetStats 获取用户统计
func (*UserService) ResetToken ¶
func (s *UserService) ResetToken(id uint, requestID string) (string, error)
ResetToken 为用户重新生成订阅 token, 让旧的 /s/<token> 链接立即失效。 不改动 UUID, 所以节点端密码/连接不受影响, 用户只需重新导入订阅。 返回当前 token. requestID (AdminUserResetRequestID) applies a retried reset once, as KernelSubscriber.ResetCredentials does: a repeat changes nothing and returns the token the first one issued, if it is still the current one.
func (*UserService) ResetTraffic ¶
func (s *UserService) ResetTraffic(id uint, requestID string) error
ResetTraffic 重置用户流量. A non-empty requestID (AdminUserResetRequestID) applies a retried reset once, through the subscriber request ledger.
func (*UserService) Update ¶
func (s *UserService) Update(id uint, updates map[string]any) error
Update 更新用户
func (*UserService) UpdateTraffic ¶
func (s *UserService) UpdateTraffic(userID uint, upload, download int64) error
UpdateTraffic 更新用户流量
func (*UserService) VerifyStepUp ¶ added in v4.1.0
func (s *UserService) VerifyStepUp(userID uint, password, code, method string) (bool, error)
VerifyStepUp re-authenticates a signed-in user before a sensitive change: with a second factor enabled, a TOTP or recovery (backup) code, checked by MFAService.Verify, which consumes a used recovery code; otherwise the current password. checked reports whether a credential was checked, which counts toward the caller's rate limit; a missing credential is not.
type UserSubscription ¶
type UserSubscription struct {
UserID uint `json:"user_id"`
Email string `json:"email"`
PlanID *uint `json:"plan_id"`
PlanName string `json:"plan_name"`
TransferEnable int64 `json:"transfer_enable"` // 总流量 (字节)
UsedTraffic int64 `json:"used_traffic"` // 已用流量 (字节)
UploadTraffic int64 `json:"upload_traffic"` // 上传流量 (字节)
DownloadTraffic int64 `json:"download_traffic"` // 下载流量 (字节)
ExpiredAt int64 `json:"expired_at"` // 到期时间
IsExpired bool `json:"is_expired"`
DaysRemaining int `json:"days_remaining"`
UsagePercent float64 `json:"usage_percent"`
SubscribePath string `json:"subscribe_path,omitempty"`
SubscribeDomains []string `json:"subscribe_domains,omitempty"`
CachedAt time.Time `json:"cached_at"`
}
UserSubscription 用户订阅详情
type UserTrafficRank ¶
type UserTrafficRank struct {
UserID uint `json:"user_id"`
Email string `json:"email"`
Traffic int64 `json:"traffic"` // 区间内总流量 (字节, 已按倍率计)
}
UserTrafficRank 单个用户的流量排行项
type WebUIExtension ¶
type WebUIExtension struct {
PluginID string `json:"plugin_id"`
PluginName string `json:"plugin_name"`
Publisher string `json:"publisher"`
Version string `json:"version"`
APIVersion string `json:"api_version"`
InstallationID uint `json:"installation_id"`
State string `json:"state"`
Bundle WebUIExtensionBundle `json:"bundle"`
Permissions []string `json:"permissions"`
Menus []PluginWebUIMenu `json:"menus"`
Routes []PluginWebUIRoute `json:"routes"`
ConfigSchema json.RawMessage `json:"config_schema"`
// ControlRoutes are the signed manifest's control routes, listed only
// when the actor may call them (the package's api permission). The web
// app reads a capability from them, such as the forward package's v4
// API (/api/v4/plugins/forward/*), which F5b's pages need.
ControlRoutes []string `json:"control_routes,omitempty"`
}
func ListEnabledWebUIExtensionsForActor ¶
func ListEnabledWebUIExtensionsForActor(db *gorm.DB, publicKey ed25519.PublicKey, actorID uint, legacyAdmin bool) ([]WebUIExtension, error)
ListEnabledWebUIExtensionsForActor applies the same authoritative plugin permissions as the control route gateway. Restricted actors only receive routes, menus and declared permissions that they can actually use.
type WebUIExtensionBundle ¶
type WireGuardPeerRotationResult ¶
WireGuardPeerRotationResult reports only non-secret rotation metadata.
func RotateWireGuardPeerKeys ¶
func RotateWireGuardPeerKeys(db *gorm.DB, protocolID uint) (*WireGuardPeerRotationResult, error)
RotateWireGuardPeerKeys replaces every selected peer's client private key, public key, and preshared key in one database transaction. Peer IDs, user assignments, and tunnel IPs remain stable so the node can apply the update without reallocating addresses.
Source Files
¶
- agent_diagnostic_actions.go
- agent_diagnostic_forward.go
- agent_diagnostic_schema.go
- agent_diagnostic_task_service.go
- agent_pki_hooks.go
- agent_plugin_install.go
- agent_plugin_lifecycle.go
- auth_rate_limit.go
- auth_registration.go
- auth_service.go
- forward_agent_bridge_service.go
- forward_agent_bridge_worker.go
- forward_ansible_stats_worker.go
- forward_background_settings.go
- forward_clean_agent_service.go
- forward_diagnosis.go
- forward_flow_reset_worker.go
- forward_gost_stats_worker.go
- forward_latency_prober.go
- forward_legacy_cleanup.go
- forward_nftables_plan.go
- forward_node_inventory_scope.go
- forward_node_schema.go
- forward_node_service.go
- forward_nodex_client.go
- forward_observability_schema.go
- forward_observability_service.go
- forward_panel_flow.go
- forward_panel_runtime_diagnostics.go
- forward_panel_runtime_service.go
- forward_panel_service.go
- forward_port_binding_schema.go
- forward_probe_address.go
- forward_rule_service.go
- forward_runtime_cleanup.go
- forward_runtime_executors.go
- forward_runtime_job_executor.go
- forward_runtime_job_payload.go
- forward_runtime_job_schema.go
- forward_runtime_path.go
- forward_runtime_provider.go
- identity_group_a.go
- init_admin.go
- init_forward_runtime_system_config.go
- init_subscription.go
- invite_code_admin.go
- invite_service.go
- kernel_identity_auth.go
- kernel_operation_view.go
- kernel_service.go
- loadbalancer_service.go
- mfa_service.go
- node_config_builder.go
- node_credential_ops.go
- node_log_service.go
- node_monthly_reset_worker.go
- node_operation_revision.go
- node_secret_validation.go
- node_secrets.go
- node_service.go
- node_traffic_series.go
- nodeops_capabilities.go
- notification_service.go
- operation_log_service.go
- order_payment.go
- order_payment_reconciler.go
- order_service.go
- package_host_migration.go
- package_report.go
- package_route_defaults.go
- package_route_mode_admin.go
- package_route_modes.go
- package_storage_lease.go
- payment_gateway_service.go
- periodic_run.go
- plan_service.go
- plugin_access.go
- plugin_bootstrap.go
- plugin_capabilities.go
- plugin_dependency_db_resolver.go
- plugin_dependency_execution_plan.go
- plugin_dependency_resolver.go
- plugin_migrations.go
- plugin_observed_state.go
- plugin_rollout.go
- plugin_runtime.go
- plugin_telemetry.go
- server_service.go
- settings_audit.go
- settings_namespaces.go
- speed_limit_service.go
- stats_schema.go
- stats_service.go
- subscriber_entitlements.go
- subscription_group_members.go
- subscription_reset.go
- subscription_service.go
- subscription_settings.go
- system_config_security.go
- system_service.go
- telegram_probe.go
- telegram_service.go
- topology_deployment_executor.go
- topology_deployment_status.go
- topology_deployment_timeline.go
- topology_diagnose.go
- topology_observed.go
- traffic_validation.go
- transaction_retry.go
- uniproxy_config.go
- user_service.go
- wireguard_peer.go
- wireguard_rotation.go
- wireguard_schema.go
- wireguard_validation.go