postgres

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package postgres implements the panel's persistence layer on top of pgx.

Index

Constants

This section is empty.

Variables

View Source
var ErrConflict = errors.New("already exists")

ErrConflict is returned when a unique constraint rejects a write.

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound is returned when a lookup by identity yields no row.

Functions

This section is empty.

Types

type HostInput

type HostInput struct {
	InboundID     string
	Remark        string
	Address       string
	Port          int
	Path          string
	SNI           string
	HostHeader    string
	ALPN          string
	Fingerprint   string
	PublicKey     string
	ShortID       string
	SpiderX       string
	Flow          string
	Security      string
	AllowInsecure bool
	Tags          []string
	IsDisabled    bool
	ViewPosition  int
}

type NodeConnectedInfo

type NodeConnectedInfo struct {
	AgentVersion  string
	XrayVersion   string
	Hostname      string
	OS            string
	Arch          string
	Kernel        string
	CPUCount      int
	CPUModel      string
	TotalRAMBytes int64
	ConfigHash    string
}

NodeConnectedInfo is written when an agent completes its handshake.

type NodeHeartbeat

type NodeHeartbeat struct {
	Health        domain.NodeHealth
	XrayRunning   bool
	XrayStartedAt *time.Time
	XrayVersion   string
	ConfigHash    string
	CPUUsage      float64
	UsedRAMBytes  int64
	TotalRAMBytes int64
	LoadAvg1      float64
	OnlineUsers   int
	Message       string
}

type NodeInput

type NodeInput struct {
	Name              string
	Address           string
	CountryCode       string
	Description       string
	IsDisabled        bool
	ConfigProfileID   *string
	ActiveInboundTags []string
	Consumption       float64
	TrafficLimitBytes int64
	TrafficReset      domain.TrafficResetStrategy
	NotifyPercent     int
	ViewPosition      int

	Provider      string
	ProviderURL   string
	CostAmount    float64
	CostCurrency  string
	BillingCycle  domain.BillingCycle
	NextPaymentAt *time.Time
	BillingNotes  string
	Tags          []string
}

type NodeSeries

type NodeSeries struct {
	NodeID   string         `json:"nodeUuid"`
	NodeName string         `json:"nodeName"`
	Points   []TrafficPoint `json:"points"`
	Total    int64          `json:"totalBytes"`
}

NodeSeries is per-node traffic over a window, grouped for stacked charts.

type Overview

type Overview struct {
	UsersTotal    int   `json:"usersTotal"`
	UsersActive   int   `json:"usersActive"`
	UsersDisabled int   `json:"usersDisabled"`
	UsersLimited  int   `json:"usersLimited"`
	UsersExpired  int   `json:"usersExpired"`
	UsersOnline   int   `json:"usersOnline"`
	NodesTotal    int   `json:"nodesTotal"`
	NodesOnline   int   `json:"nodesOnline"`
	NodesDisabled int   `json:"nodesDisabled"`
	HostsTotal    int   `json:"hostsTotal"`
	SquadsTotal   int   `json:"squadsTotal"`
	ProfilesTotal int   `json:"profilesTotal"`
	TrafficDay    int64 `json:"trafficLast24hBytes"`
	TrafficWeek   int64 `json:"trafficLast7dBytes"`
	TrafficMonth  int64 `json:"trafficLast30dBytes"`
	TrafficTotal  int64 `json:"trafficTotalBytes"`
}

Overview is the aggregate shown on the dashboard landing page.

type ProviderSpend

type ProviderSpend struct {
	Provider string  `json:"provider"`
	Nodes    int     `json:"nodes"`
	Monthly  float64 `json:"monthly"`
}

type ProvisionedUser

type ProvisionedUser struct {
	UUID           string
	Username       string
	VlessUUID      string
	TrojanPassword string
	SSPassword     string
	InboundTag     string
}

ProvisionedUser is the minimal projection the orchestrator needs to inject a client into an xray inbound.

type SpendSummary

type SpendSummary struct {
	Currency       string          `json:"currency"`
	MonthlyTotal   float64         `json:"monthlyTotal"`
	YearlyTotal    float64         `json:"yearlyTotal"`
	BilledNodes    int             `json:"billedNodes"`
	CostPerTB      float64         `json:"costPerTb"`
	TrafficMonthTB float64         `json:"trafficThisMonthTb"`
	ByProvider     []ProviderSpend `json:"byProvider"`
	Upcoming       []UpcomingBill  `json:"upcoming"`
	Overdue        int             `json:"overdue"`
}

SpendSummary is the infrastructure cost picture shown on the dashboard.

type Store

type Store struct {
	// contains filtered or unexported fields
}

func Connect

func Connect(ctx context.Context, dsn string) (*Store, error)

func (*Store) APITokenByHash

func (s *Store) APITokenByHash(ctx context.Context, hash string) (*domain.APIToken, error)

APITokenByHash resolves a presented token and rejects expired ones.

func (*Store) AddAllUsersToSquad

func (s *Store) AddAllUsersToSquad(ctx context.Context, squadID string) (int64, error)

AddAllUsersToSquad and RemoveAllUsersFromSquad back the bulk membership actions offered on the squad page.

func (*Store) AddNodeTraffic

func (s *Store) AddNodeTraffic(ctx context.Context, id string, bytes int64) error

func (*Store) AddUserTraffic

func (s *Store) AddUserTraffic(ctx context.Context, userID string, bytes int64) (used, limit int64, status domain.UserStatus, err error)

AddUserTraffic charges usage to a user and returns the user's post-update state so the caller can enforce limits.

func (*Store) AdminByUUID

func (s *Store) AdminByUUID(ctx context.Context, id string) (*domain.Admin, error)

func (*Store) AdminByUsername

func (s *Store) AdminByUsername(ctx context.Context, username string) (*domain.Admin, error)

func (*Store) ApplyNodeHeartbeat

func (s *Store) ApplyNodeHeartbeat(ctx context.Context, id string, hb NodeHeartbeat) error

func (*Store) Close

func (s *Store) Close()

func (*Store) CountAdmins

func (s *Store) CountAdmins(ctx context.Context) (int, error)

func (*Store) CreateAPIToken

func (s *Store) CreateAPIToken(ctx context.Context, name, hash, preview, createdBy string, expiresAt *time.Time) (*domain.APIToken, error)

func (*Store) CreateAdmin

func (s *Store) CreateAdmin(ctx context.Context, username, passwordHash string, role domain.AdminRole) (*domain.Admin, error)

func (*Store) CreateHost

func (s *Store) CreateHost(ctx context.Context, in HostInput) (*domain.Host, error)

func (*Store) CreateNode

func (s *Store) CreateNode(ctx context.Context, in NodeInput, tokenHash, tokenPreview string) (*domain.Node, error)

func (*Store) CreateProfile

func (s *Store) CreateProfile(ctx context.Context, name string, config json.RawMessage, inbounds []domain.ConfigProfileInbound) (*domain.ConfigProfile, error)

func (*Store) CreateSquad

func (s *Store) CreateSquad(ctx context.Context, name, info string, inboundIDs []string) (*domain.Squad, error)

func (*Store) CreateUser

func (s *Store) CreateUser(ctx context.Context, in UserInput, sec UserSecrets) (*domain.User, error)

func (*Store) DeleteAPIToken

func (s *Store) DeleteAPIToken(ctx context.Context, id string) error

func (*Store) DeleteAdmin

func (s *Store) DeleteAdmin(ctx context.Context, id string) error

func (*Store) DeleteDevice

func (s *Store) DeleteDevice(ctx context.Context, userID, hwid string) error

func (*Store) DeleteHost

func (s *Store) DeleteHost(ctx context.Context, id string) error

func (*Store) DeleteNode

func (s *Store) DeleteNode(ctx context.Context, id string) error

func (*Store) DeleteProfile

func (s *Store) DeleteProfile(ctx context.Context, id string) error

func (*Store) DeleteSquad

func (s *Store) DeleteSquad(ctx context.Context, id string) error

func (*Store) DeleteUser

func (s *Store) DeleteUser(ctx context.Context, id string) error

func (*Store) ExpireUsers

func (s *Store) ExpireUsers(ctx context.Context) (int64, error)

ExpireUsers flips past-due active users to EXPIRED and returns how many changed.

func (*Store) Host

func (s *Store) Host(ctx context.Context, id string) (*domain.Host, error)

func (*Store) HostsForInbounds

func (s *Store) HostsForInbounds(ctx context.Context, inboundIDs []string) ([]domain.Host, error)

HostsForInbounds returns the enabled hosts published by any of the inbounds, which is how a user's subscription is assembled from their squads.

func (*Store) Inbound

func (s *Store) Inbound(ctx context.Context, id string) (*domain.ConfigProfileInbound, error)

func (*Store) ListAPITokens

func (s *Store) ListAPITokens(ctx context.Context) ([]domain.APIToken, error)

func (*Store) ListAdmins

func (s *Store) ListAdmins(ctx context.Context) ([]domain.Admin, error)

func (*Store) ListEvents

func (s *Store) ListEvents(ctx context.Context, limit int, kind string) ([]domain.Event, error)

func (*Store) ListHosts

func (s *Store) ListHosts(ctx context.Context) ([]domain.Host, error)

func (*Store) ListNodes

func (s *Store) ListNodes(ctx context.Context) ([]domain.Node, error)

func (*Store) ListProfiles

func (s *Store) ListProfiles(ctx context.Context) ([]domain.ConfigProfile, error)

func (*Store) ListSquads

func (s *Store) ListSquads(ctx context.Context) ([]domain.Squad, error)

func (*Store) ListUsers

func (s *Store) ListUsers(ctx context.Context, f UserFilter) ([]domain.User, int, error)

func (*Store) LogEvent

func (s *Store) LogEvent(ctx context.Context, kind domain.EventKind, actor, subject, message string, meta any)

func (*Store) MarkAllNodesDisconnected

func (s *Store) MarkAllNodesDisconnected(ctx context.Context) error

MarkAllNodesDisconnected resets liveness state on panel start, since no agent stream survives a restart.

func (*Store) MarkNodeConnected

func (s *Store) MarkNodeConnected(ctx context.Context, id string, info NodeConnectedInfo) error

func (*Store) MarkNodeDisconnected

func (s *Store) MarkNodeDisconnected(ctx context.Context, id, reason string) error

func (*Store) MarkUserOnline

func (s *Store) MarkUserOnline(ctx context.Context, userID string)

func (*Store) Migrate

func (s *Store) Migrate(ctx context.Context) error

Migrate applies every embedded migration that has not run yet.

func (*Store) Node

func (s *Store) Node(ctx context.Context, id string) (*domain.Node, error)

func (*Store) NodeTrafficSeries

func (s *Store) NodeTrafficSeries(ctx context.Context, since time.Time, interval string) ([]NodeSeries, error)

func (*Store) NodesUsingProfile

func (s *Store) NodesUsingProfile(ctx context.Context, profileID string) ([]domain.Node, error)

NodesUsingProfile lists the nodes bound to a profile, used to fan out config changes after the profile document is edited.

func (*Store) Overview

func (s *Store) Overview(ctx context.Context) (*Overview, error)

func (*Store) Pool

func (s *Store) Pool() *pgxpool.Pool

func (*Store) Profile

func (s *Store) Profile(ctx context.Context, id string) (*domain.ConfigProfile, error)

func (*Store) ProfileInbounds

func (s *Store) ProfileInbounds(ctx context.Context, profileID string) ([]domain.ConfigProfileInbound, error)

ProfileInbounds returns the inbounds of one profile, or of every profile when profileID is empty.

func (*Store) PruneUsage

func (s *Store) PruneUsage(ctx context.Context, retention time.Duration) error

PruneUsage drops history older than the retention window.

func (*Store) RecordNodeUsage

func (s *Store) RecordNodeUsage(ctx context.Context, nodeID string, at time.Time, bytes int64) error

func (*Store) RecordUserUsage

func (s *Store) RecordUserUsage(ctx context.Context, userID, nodeID string, at time.Time, bytes int64) error

func (*Store) RemoveAllUsersFromSquad

func (s *Store) RemoveAllUsersFromSquad(ctx context.Context, squadID string) (int64, error)

func (*Store) ReorderHosts

func (s *Store) ReorderHosts(ctx context.Context, order []string) error

func (*Store) ResetDevices

func (s *Store) ResetDevices(ctx context.Context, userID string) error

func (*Store) ResetDueUserTraffic

func (s *Store) ResetDueUserTraffic(ctx context.Context) (int64, error)

ResetDueUserTraffic applies the per-user reset strategy and returns how many counters were rolled over.

func (*Store) ResetNodeTraffic

func (s *Store) ResetNodeTraffic(ctx context.Context, id string) error

func (*Store) ResetUserTraffic

func (s *Store) ResetUserTraffic(ctx context.Context, id string) error

func (*Store) RevokeUserSubscription

func (s *Store) RevokeUserSubscription(ctx context.Context, id, newSubUUID, newShort, newVless, newTrojan, newSS string) (*domain.User, error)

func (*Store) RollDuePayments

func (s *Store) RollDuePayments(ctx context.Context) ([]domain.Node, error)

RollDuePayments moves past-due nodes onto their next billing date and reports which ones rolled over, so the operator gets one notice per cycle.

func (*Store) RotateNodeToken

func (s *Store) RotateNodeToken(ctx context.Context, id, tokenHash, tokenPreview string) error

func (*Store) SetNodeConfigHash

func (s *Store) SetNodeConfigHash(ctx context.Context, id, hash string) error

func (*Store) SetNodeDisabled

func (s *Store) SetNodeDisabled(ctx context.Context, id string, disabled bool) error

func (*Store) SetNodeHealth

func (s *Store) SetNodeHealth(ctx context.Context, id string, health domain.NodeHealth, message string) error

func (*Store) SetUserStatus

func (s *Store) SetUserStatus(ctx context.Context, id string, status domain.UserStatus) error

func (*Store) Settings

func (s *Store) Settings(ctx context.Context) (*domain.Settings, error)

Settings returns the singleton settings row, creating it if a very old installation somehow lacks one.

func (*Store) Spend

func (s *Store) Spend(ctx context.Context, defaultCurrency string) (*SpendSummary, error)

Spend aggregates node costs. Amounts are normalised to a monthly figure so nodes on different billing cycles can be compared and summed.

func (*Store) Squad

func (s *Store) Squad(ctx context.Context, id string) (*domain.Squad, error)

func (*Store) TopUsers

func (s *Store) TopUsers(ctx context.Context, since time.Time, limit int) ([]TopUser, error)

func (*Store) TotalTrafficSeries

func (s *Store) TotalTrafficSeries(ctx context.Context, since time.Time, interval string) ([]TrafficPoint, error)

func (*Store) TouchAdminLogin

func (s *Store) TouchAdminLogin(ctx context.Context, id string)

func (*Store) TouchDevice

func (s *Store) TouchDevice(ctx context.Context, userID, hwid, userAgent, platform string, limit int) (allowed bool, count int, err error)

TouchDevice records a device against a subscription and reports whether the user is over their limit. A device already known never counts as new, so a returning client is not locked out by its own history.

func (*Store) TouchSubscriptionOpen

func (s *Store) TouchSubscriptionOpen(ctx context.Context, id, userAgent string)

func (*Store) UpdateAdmin

func (s *Store) UpdateAdmin(ctx context.Context, id string, role domain.AdminRole, disabled bool) (*domain.Admin, error)

func (*Store) UpdateAdminPassword

func (s *Store) UpdateAdminPassword(ctx context.Context, id, passwordHash string) error

func (*Store) UpdateHost

func (s *Store) UpdateHost(ctx context.Context, id string, in HostInput) (*domain.Host, error)

func (*Store) UpdateNode

func (s *Store) UpdateNode(ctx context.Context, id string, in NodeInput) (*domain.Node, error)

func (*Store) UpdateProfile

func (s *Store) UpdateProfile(ctx context.Context, id, name string, config json.RawMessage, inbounds []domain.ConfigProfileInbound) (*domain.ConfigProfile, error)

UpdateProfile rewrites the document and reconciles the extracted inbound rows. Inbounds are matched by tag so hosts and squads keep pointing at the same inbound identity across edits.

func (*Store) UpdateSettings

func (s *Store) UpdateSettings(ctx context.Context, in domain.Settings) (*domain.Settings, error)

func (*Store) UpdateSquad

func (s *Store) UpdateSquad(ctx context.Context, id, name, info string, inboundIDs []string) (*domain.Squad, error)

func (*Store) UpdateUser

func (s *Store) UpdateUser(ctx context.Context, id string, in UserInput) (*domain.User, error)

func (*Store) User

func (s *Store) User(ctx context.Context, id string) (*domain.User, error)

func (*Store) UserByShortUUID

func (s *Store) UserByShortUUID(ctx context.Context, short string) (*domain.User, error)

func (*Store) UserBySubscription

func (s *Store) UserBySubscription(ctx context.Context, subUUID string) (*domain.User, error)

func (*Store) UserDevices

func (s *Store) UserDevices(ctx context.Context, userID string) ([]domain.Device, error)

func (*Store) UserInboundIDs

func (s *Store) UserInboundIDs(ctx context.Context, userID string) ([]string, error)

UserInboundIDs lists the inbound identities a user can reach through their squads.

func (*Store) UserTags

func (s *Store) UserTags(ctx context.Context) ([]string, error)

func (*Store) UserTrafficSeries

func (s *Store) UserTrafficSeries(ctx context.Context, userID string, since time.Time) ([]TrafficPoint, error)

func (*Store) UsersForNode

func (s *Store) UsersForNode(ctx context.Context, profileID string, inboundTags []string) ([]ProvisionedUser, error)

UsersForNode returns every (user, inbound tag) pair that should be present in the config of the given node: active users, in a squad, whose squad grants an inbound of the node's profile that the node actually serves.

type TopUser

type TopUser struct {
	UserID   string `json:"uuid"`
	Username string `json:"username"`
	Bytes    int64  `json:"bytes"`
}

TopUser is an entry of the "biggest consumers" dashboard widget.

type TrafficPoint

type TrafficPoint struct {
	At    time.Time `json:"at"`
	Bytes int64     `json:"bytes"`
}

TrafficPoint is one row of a time series returned to the dashboard.

type UpcomingBill

type UpcomingBill struct {
	NodeID   string    `json:"nodeUuid"`
	NodeName string    `json:"nodeName"`
	Provider string    `json:"provider"`
	Amount   float64   `json:"amount"`
	Currency string    `json:"currency"`
	DueAt    time.Time `json:"dueAt"`
	DaysLeft int       `json:"daysLeft"`
}

type UserFilter

type UserFilter struct {
	Search  string
	Status  string
	SquadID string
	Tag     string
	Limit   int
	Offset  int
	SortBy  string
	Desc    bool
}

type UserInput

type UserInput struct {
	Username          string
	Status            domain.UserStatus
	TrafficLimitBytes int64
	TrafficReset      domain.TrafficResetStrategy
	ExpireAt          *time.Time
	Description       string
	Tag               string
	Email             string
	TelegramID        *int64
	HWIDDeviceLimit   int
	SquadIDs          []string
}

type UserSecrets

type UserSecrets struct {
	ShortUUID        string
	SubscriptionUUID string
	VlessUUID        string
	TrojanPassword   string
	SSPassword       string
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL