Documentation
¶
Overview ¶
Package postgres implements the panel's persistence layer on top of pgx.
Index ¶
- Variables
- type HostInput
- type NodeConnectedInfo
- type NodeHeartbeat
- type NodeInput
- type NodeSeries
- type Overview
- type ProviderSpend
- type ProvisionedUser
- type SpendSummary
- type Store
- func (s *Store) APITokenByHash(ctx context.Context, hash string) (*domain.APIToken, error)
- func (s *Store) AddAllUsersToSquad(ctx context.Context, squadID string) (int64, error)
- func (s *Store) AddNodeTraffic(ctx context.Context, id string, bytes int64) error
- func (s *Store) AddUserTraffic(ctx context.Context, userID string, bytes int64) (used, limit int64, status domain.UserStatus, err error)
- func (s *Store) AdminByUUID(ctx context.Context, id string) (*domain.Admin, error)
- func (s *Store) AdminByUsername(ctx context.Context, username string) (*domain.Admin, error)
- func (s *Store) ApplyNodeHeartbeat(ctx context.Context, id string, hb NodeHeartbeat) error
- func (s *Store) Channel(ctx context.Context, id string) (*domain.NotificationChannel, error)
- func (s *Store) ChannelDeliveries(ctx context.Context, id string, limit int) ([]domain.NotificationDelivery, error)
- func (s *Store) Close()
- func (s *Store) CountAdmins(ctx context.Context) (int, error)
- func (s *Store) CreateAPIToken(ctx context.Context, name, hash, preview, createdBy string, ...) (*domain.APIToken, error)
- func (s *Store) CreateAdmin(ctx context.Context, username, passwordHash string, role domain.AdminRole) (*domain.Admin, error)
- func (s *Store) CreateAnnouncement(ctx context.Context, a domain.Announcement) (*domain.Announcement, error)
- func (s *Store) CreateChannel(ctx context.Context, c domain.NotificationChannel) (*domain.NotificationChannel, error)
- func (s *Store) CreateHost(ctx context.Context, in HostInput) (*domain.Host, error)
- func (s *Store) CreateNode(ctx context.Context, in NodeInput, tokenHash, tokenPreview string) (*domain.Node, error)
- func (s *Store) CreateProfile(ctx context.Context, name string, config json.RawMessage, ...) (*domain.ConfigProfile, error)
- func (s *Store) CreateSquad(ctx context.Context, name, info string, inboundIDs []string) (*domain.Squad, error)
- func (s *Store) CreateUser(ctx context.Context, in UserInput, sec UserSecrets) (*domain.User, error)
- func (s *Store) DeleteAPIToken(ctx context.Context, id string) error
- func (s *Store) DeleteAdmin(ctx context.Context, id string) error
- func (s *Store) DeleteAnnouncement(ctx context.Context, id string) error
- func (s *Store) DeleteChannel(ctx context.Context, id string) error
- func (s *Store) DeleteDevice(ctx context.Context, userID, hwid string) error
- func (s *Store) DeleteHost(ctx context.Context, id string) error
- func (s *Store) DeleteNode(ctx context.Context, id string) error
- func (s *Store) DeleteProfile(ctx context.Context, id string) error
- func (s *Store) DeleteSquad(ctx context.Context, id string) error
- func (s *Store) DeleteUser(ctx context.Context, id string) error
- func (s *Store) EnabledChannels(ctx context.Context) ([]domain.NotificationChannel, error)
- func (s *Store) ExpireUsers(ctx context.Context) (int64, error)
- func (s *Store) Host(ctx context.Context, id string) (*domain.Host, error)
- func (s *Store) HostsForInbounds(ctx context.Context, inboundIDs []string) ([]domain.Host, error)
- func (s *Store) Inbound(ctx context.Context, id string) (*domain.ConfigProfileInbound, error)
- func (s *Store) ListAPITokens(ctx context.Context) ([]domain.APIToken, error)
- func (s *Store) ListAdmins(ctx context.Context) ([]domain.Admin, error)
- func (s *Store) ListAnnouncements(ctx context.Context) ([]domain.Announcement, error)
- func (s *Store) ListChannels(ctx context.Context) ([]domain.NotificationChannel, error)
- func (s *Store) ListEvents(ctx context.Context, limit int, kind string) ([]domain.Event, error)
- func (s *Store) ListHosts(ctx context.Context) ([]domain.Host, error)
- func (s *Store) ListNodes(ctx context.Context) ([]domain.Node, error)
- func (s *Store) ListProfiles(ctx context.Context) ([]domain.ConfigProfile, error)
- func (s *Store) ListSquads(ctx context.Context) ([]domain.Squad, error)
- func (s *Store) ListUsers(ctx context.Context, f UserFilter) ([]domain.User, int, error)
- func (s *Store) LiveAnnouncements(ctx context.Context) ([]domain.Announcement, error)
- func (s *Store) LogEvent(ctx context.Context, kind domain.EventKind, actor, subject, message string, ...)
- func (s *Store) MarkAllNodesDisconnected(ctx context.Context) error
- func (s *Store) MarkNodeConnected(ctx context.Context, id string, info NodeConnectedInfo) error
- func (s *Store) MarkNodeDisconnected(ctx context.Context, id, reason string) error
- func (s *Store) MarkUserOnline(ctx context.Context, userID string)
- func (s *Store) Migrate(ctx context.Context) error
- func (s *Store) Node(ctx context.Context, id string) (*domain.Node, error)
- func (s *Store) NodeMetrics(ctx context.Context, nodeID string, since time.Duration) ([]domain.NodeMetric, error)
- func (s *Store) NodeTrafficSeries(ctx context.Context, since time.Time, interval string) ([]NodeSeries, error)
- func (s *Store) NodesUsingProfile(ctx context.Context, profileID string) ([]domain.Node, error)
- func (s *Store) OnEvent(fn func(domain.Event))
- func (s *Store) Overview(ctx context.Context) (*Overview, error)
- func (s *Store) Pool() *pgxpool.Pool
- func (s *Store) Profile(ctx context.Context, id string) (*domain.ConfigProfile, error)
- func (s *Store) ProfileInbounds(ctx context.Context, profileID string) ([]domain.ConfigProfileInbound, error)
- func (s *Store) PruneDeliveries(ctx context.Context, keepFor time.Duration) error
- func (s *Store) PruneNodeMetrics(ctx context.Context, keepFor time.Duration) error
- func (s *Store) PruneUsage(ctx context.Context, retention time.Duration) error
- func (s *Store) RecordDelivery(ctx context.Context, d domain.NotificationDelivery) error
- func (s *Store) RecordNodeMetric(ctx context.Context, nodeID string, m domain.NodeMetric) error
- func (s *Store) RecordNodeUsage(ctx context.Context, nodeID string, at time.Time, bytes int64) error
- func (s *Store) RecordUserUsage(ctx context.Context, userID, nodeID string, at time.Time, bytes int64) error
- func (s *Store) RemoveAllUsersFromSquad(ctx context.Context, squadID string) (int64, error)
- func (s *Store) ReorderHosts(ctx context.Context, order []string) error
- func (s *Store) ResetDevices(ctx context.Context, userID string) error
- func (s *Store) ResetDueUserTraffic(ctx context.Context) (int64, error)
- func (s *Store) ResetNodeTraffic(ctx context.Context, id string) error
- func (s *Store) ResetUserTraffic(ctx context.Context, id string) error
- func (s *Store) RevokeUserSubscription(ctx context.Context, ...) (*domain.User, error)
- func (s *Store) RollDuePayments(ctx context.Context) ([]domain.Node, error)
- func (s *Store) RotateNodeToken(ctx context.Context, id, tokenHash, tokenPreview string) error
- func (s *Store) SetNodeConfigHash(ctx context.Context, id, hash string) error
- func (s *Store) SetNodeDisabled(ctx context.Context, id string, disabled bool) error
- func (s *Store) SetNodeHealth(ctx context.Context, id string, health domain.NodeHealth, message string) error
- func (s *Store) SetUserStatus(ctx context.Context, id string, status domain.UserStatus) error
- func (s *Store) Settings(ctx context.Context) (*domain.Settings, error)
- func (s *Store) Spend(ctx context.Context, defaultCurrency string) (*SpendSummary, error)
- func (s *Store) Squad(ctx context.Context, id string) (*domain.Squad, error)
- func (s *Store) TopUsers(ctx context.Context, since time.Time, limit int) ([]TopUser, error)
- func (s *Store) TotalTrafficSeries(ctx context.Context, since time.Time, interval string) ([]TrafficPoint, error)
- func (s *Store) TouchAdminLogin(ctx context.Context, id string)
- func (s *Store) TouchDevice(ctx context.Context, userID, hwid, userAgent, platform string, limit int) (allowed bool, count int, err error)
- func (s *Store) TouchSubscriptionOpen(ctx context.Context, id, userAgent string)
- func (s *Store) UpdateAdmin(ctx context.Context, id string, role domain.AdminRole, disabled bool) (*domain.Admin, error)
- func (s *Store) UpdateAdminPassword(ctx context.Context, id, passwordHash string) error
- func (s *Store) UpdateAnnouncement(ctx context.Context, id string, a domain.Announcement) (*domain.Announcement, error)
- func (s *Store) UpdateChannel(ctx context.Context, id string, c domain.NotificationChannel) (*domain.NotificationChannel, error)
- func (s *Store) UpdateHost(ctx context.Context, id string, in HostInput) (*domain.Host, error)
- func (s *Store) UpdateNode(ctx context.Context, id string, in NodeInput) (*domain.Node, error)
- func (s *Store) UpdateProfile(ctx context.Context, id, name string, config json.RawMessage, ...) (*domain.ConfigProfile, error)
- func (s *Store) UpdateSettings(ctx context.Context, in domain.Settings) (*domain.Settings, error)
- func (s *Store) UpdateSquad(ctx context.Context, id, name, info string, inboundIDs []string) (*domain.Squad, error)
- func (s *Store) UpdateUser(ctx context.Context, id string, in UserInput) (*domain.User, error)
- func (s *Store) User(ctx context.Context, id string) (*domain.User, error)
- func (s *Store) UserByShortUUID(ctx context.Context, short string) (*domain.User, error)
- func (s *Store) UserBySubscription(ctx context.Context, subUUID string) (*domain.User, error)
- func (s *Store) UserDevices(ctx context.Context, userID string) ([]domain.Device, error)
- func (s *Store) UserInboundIDs(ctx context.Context, userID string) ([]string, error)
- func (s *Store) UserTags(ctx context.Context) ([]string, error)
- func (s *Store) UserTrafficSeries(ctx context.Context, userID string, since time.Time) ([]TrafficPoint, error)
- func (s *Store) UsersForNode(ctx context.Context, profileID string, inboundTags []string) ([]ProvisionedUser, error)
- type TopUser
- type TrafficPoint
- type UpcomingBill
- type UserFilter
- type UserInput
- type UserSecrets
Constants ¶
This section is empty.
Variables ¶
var ErrConflict = errors.New("already exists")
ErrConflict is returned when a unique constraint rejects a write.
var ErrNotFound = errors.New("not found")
ErrNotFound is returned when a lookup by identity yields no row.
Functions ¶
This section is empty.
Types ¶
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 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 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 (*Store) APITokenByHash ¶
APITokenByHash resolves a presented token and rejects expired ones.
func (*Store) AddAllUsersToSquad ¶
AddAllUsersToSquad and RemoveAllUsersFromSquad back the bulk membership actions offered on the squad page.
func (*Store) AddNodeTraffic ¶
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 (*Store) AdminByUsername ¶
func (*Store) ApplyNodeHeartbeat ¶
func (*Store) ChannelDeliveries ¶ added in v0.2.0
func (*Store) CreateAPIToken ¶
func (*Store) CreateAdmin ¶
func (*Store) CreateAnnouncement ¶ added in v0.2.0
func (s *Store) CreateAnnouncement(ctx context.Context, a domain.Announcement) (*domain.Announcement, error)
func (*Store) CreateChannel ¶ added in v0.2.0
func (s *Store) CreateChannel(ctx context.Context, c domain.NotificationChannel) (*domain.NotificationChannel, error)
func (*Store) CreateHost ¶
func (*Store) CreateNode ¶
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 (*Store) CreateUser ¶
func (*Store) DeleteAnnouncement ¶ added in v0.2.0
func (*Store) DeleteChannel ¶ added in v0.2.0
func (*Store) DeleteDevice ¶
func (*Store) EnabledChannels ¶ added in v0.2.0
EnabledChannels is the dispatcher's read path, kept separate so a disabled channel costs nothing at delivery time.
func (*Store) ExpireUsers ¶
ExpireUsers flips past-due active users to EXPIRED and returns how many changed.
func (*Store) HostsForInbounds ¶
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) ListAPITokens ¶
func (*Store) ListAnnouncements ¶ added in v0.2.0
func (*Store) ListChannels ¶ added in v0.2.0
func (*Store) ListEvents ¶
func (*Store) ListProfiles ¶
func (*Store) LiveAnnouncements ¶ added in v0.2.0
LiveAnnouncements is what a subscriber sees. The window is filtered in SQL so the subscription path stays one query regardless of how many notices have accumulated over the life of the deployment.
func (*Store) MarkAllNodesDisconnected ¶
MarkAllNodesDisconnected resets liveness state on panel start, since no agent stream survives a restart.
func (*Store) MarkNodeConnected ¶
func (*Store) MarkNodeDisconnected ¶
func (*Store) NodeMetrics ¶ added in v0.2.0
func (*Store) NodeTrafficSeries ¶
func (*Store) NodesUsingProfile ¶
NodesUsingProfile lists the nodes bound to a profile, used to fan out config changes after the profile document is edited.
func (*Store) OnEvent ¶ added in v0.2.0
OnEvent registers the hook LogEvent calls. Passing nil detaches it.
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) PruneDeliveries ¶ added in v0.2.0
PruneDeliveries keeps the log from growing without bound. A panel that notifies on every user update produces a lot of rows, and none of them are interesting a week later.
func (*Store) PruneNodeMetrics ¶ added in v0.2.0
func (*Store) PruneUsage ¶
PruneUsage drops history older than the retention window.
func (*Store) RecordDelivery ¶ added in v0.2.0
RecordDelivery appends to the delivery log and rolls the denormalised health fields on the channel in the same statement pair, so the list view and the log can never disagree about the last outcome.
func (*Store) RecordNodeMetric ¶ added in v0.2.0
RecordNodeMetric stores one heartbeat sample. Samples are keyed by minute so a chatty agent cannot flood the table — a node heartbeating every few seconds would otherwise write tens of thousands of rows a day for a chart that is read at minute resolution anyway.
func (*Store) RecordNodeUsage ¶
func (*Store) RecordUserUsage ¶
func (*Store) RemoveAllUsersFromSquad ¶
func (*Store) ReorderHosts ¶
func (*Store) ResetDueUserTraffic ¶
ResetDueUserTraffic applies the per-user reset strategy and returns how many counters were rolled over.
func (*Store) ResetNodeTraffic ¶
func (*Store) ResetUserTraffic ¶
func (*Store) RevokeUserSubscription ¶
func (*Store) RollDuePayments ¶
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 (*Store) SetNodeConfigHash ¶
func (*Store) SetNodeDisabled ¶
func (*Store) SetNodeHealth ¶
func (*Store) SetUserStatus ¶
func (*Store) Settings ¶
Settings returns the singleton settings row, creating it if a very old installation somehow lacks one.
func (*Store) Spend ¶
Spend aggregates node costs. Amounts are normalised to a monthly figure so nodes on different billing cycles can be compared and summed.
func (*Store) TotalTrafficSeries ¶
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 (*Store) UpdateAdmin ¶
func (*Store) UpdateAdminPassword ¶
func (*Store) UpdateAnnouncement ¶ added in v0.2.0
func (s *Store) UpdateAnnouncement(ctx context.Context, id string, a domain.Announcement) (*domain.Announcement, error)
func (*Store) UpdateChannel ¶ added in v0.2.0
func (s *Store) UpdateChannel(ctx context.Context, id string, c domain.NotificationChannel) (*domain.NotificationChannel, error)
func (*Store) UpdateHost ¶
func (*Store) UpdateNode ¶
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 (*Store) UpdateSquad ¶
func (*Store) UpdateUser ¶
func (*Store) UserByShortUUID ¶
func (*Store) UserBySubscription ¶
func (*Store) UserDevices ¶
func (*Store) UserInboundIDs ¶
UserInboundIDs lists the inbound identities a user can reach through their squads.
func (*Store) UserTrafficSeries ¶
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 ¶
TrafficPoint is one row of a time series returned to the dashboard.