shared

package
v1.25.0 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: AGPL-3.0 Imports: 14 Imported by: 0

Documentation

Index

Constants

View Source
const (
	CONTROLLER_DASHBOARD  = "dashboard"
	CONTROLLER_VISITORS   = "visitors"
	CONTROLLER_SESSIONS   = "sessions"
	CONTROLLER_SETTINGS   = "settings"
	CONTROLLER_IP_DETAILS = "ip-details"
)
View Source
const (
	ParamController = "controller"
	ParamAction     = "action"
	ParamPeriod     = "period"
	ParamCountry    = "country"
	ParamDeviceType = "device_type"
	ParamPath       = "path"
	ParamDateFrom   = "date_from"
	ParamDateTo     = "date_to"
	ParamPage       = "page"
	ParamIP         = "ip"
)

Query parameter names

View Source
const (
	PeriodToday     = "today"
	PeriodYesterday = "yesterday"
	PeriodLast7Days = "last-7-days"
	PeriodThisMonth = "this-month"
	PeriodLastMonth = "last-month"
	PeriodAllTime   = "all-time"
	PeriodDefault   = PeriodLast7Days
)

Period identifiers

View Source
const (
	DefaultPageSize = 25
	MaxPageSize     = 100
)

Pagination

View Source
const BotSourceIdentified = "identified"

BotSourceIdentified means the IP was added via the "Identify Bots" scan.

View Source
const BotSourceManual = "manual"

BotSourceManual means the IP was added manually by the user.

View Source
const SettingKeyBotIPs = "bot_ips"

SettingKeyBotIPs is the key under which bot IP records are stored as a JSON array in the stats store's settings table.

Variables

This section is empty.

Functions

func AddBotRecord added in v1.25.0

func AddBotRecord(ctx context.Context, store statsstore.StoreInterface, record BotRecord) error

AddBotRecord adds a single bot record, avoiding duplicates by IP.

func AddBotRecords added in v1.25.0

func AddBotRecords(ctx context.Context, store statsstore.StoreInterface, newRecords []BotRecord) error

AddBotRecords batch-adds multiple bot records in a single store write, skipping any IPs that already exist in the list.

func AssertContains added in v1.25.0

func AssertContains(t testing.TB, body, substr string)

AssertContains checks that the body contains a substring, failing the test with a clear message if not.

func Breadcrumbs(items []Breadcrumb) hb.TagInterface

Breadcrumbs renders a breadcrumb navigation trail from the given entries. The last entry should have an empty URL to indicate the current page.

func FlagIPVisitorsAsBot added in v1.25.0

func FlagIPVisitorsAsBot(ctx context.Context, store statsstore.StoreInterface, ip string) (int, error)

FlagIPVisitorsAsBot sets bot='yes' on all visitor records for the given IP. Returns the number of visitor records that were found (regardless of whether they were already flagged). If no visitor records exist for the IP, returns (0, nil) — callers should check the count and warn the user accordingly.

func FlashOrRedirect added in v1.25.0

func FlashOrRedirect(opts ControllerOptions, w http.ResponseWriter, r *http.Request, message string, redirectURL string, delaySeconds int) string

FlashOrRedirect renders a flash error message via the FlashError callback when configured, otherwise falls back to a plain HTTP redirect. It returns the response body string (matching the controller Handler signature).

func GetBotIPs added in v1.25.0

func GetBotIPs(ctx context.Context, store statsstore.StoreInterface) []string

GetBotIPs returns just the IP strings from the bot records.

func NewTestControllerOptions added in v1.25.0

func NewTestControllerOptions(t testing.TB) (ControllerOptions, *FakeLayout, statsstore.StoreInterface)

NewTestControllerOptions builds a ControllerOptions wired to a test store and FakeLayout, suitable for controller tests.

func NewTestStore added in v1.25.0

func NewTestStore(t testing.TB) statsstore.StoreInterface

NewTestStore creates an in-memory SQLite statsstore for testing. It auto-migrates the visitor table and registers a cleanup via t.Cleanup.

func PeriodOptions added in v1.25.0

func PeriodOptions() []struct{ Value, Label string }

PeriodOptions returns the ordered list of selectable periods for the UI.

func RemoveBotRecord added in v1.25.0

func RemoveBotRecord(ctx context.Context, store statsstore.StoreInterface, ip string) error

RemoveBotRecord removes a bot record by IP.

func SaveBotRecords added in v1.25.0

func SaveBotRecords(ctx context.Context, store statsstore.StoreInterface, records []BotRecord) error

SaveBotRecords writes the full bot records to the stats store settings.

func SeedVisitor added in v1.25.0

func SeedVisitor(t testing.TB, store statsstore.StoreInterface, ip, path, country string)

SeedVisitor creates a single visitor record in the store for testing.

Types

type BotReason added in v1.25.0

type BotReason struct {
	Pattern string `json:"pattern"` // the matched bot-page pattern (e.g. "sitemap.xml")
	Path    string `json:"path"`    // sample visitor paths
	Hits    int    `json:"hits"`    // how many times this pattern was hit
}

BotReason captures a single piece of evidence that caused an IP to be flagged as a bot (e.g. it visited sitemap.xml 3 times).

type BotRecord added in v1.25.0

type BotRecord struct {
	IP      string      `json:"ip"`
	AddedAt string      `json:"added_at"` // "YYYY-MM-DD HH:MM:SS" UTC
	Source  string      `json:"source"`   // "identified" or "manual"
	Reasons []BotReason `json:"reasons"`
}

BotRecord is the full record for a single flagged bot IP.

func GetBotRecords added in v1.25.0

func GetBotRecords(ctx context.Context, store statsstore.StoreInterface) []BotRecord

GetBotRecords reads the full bot IP records from the stats store settings.

type Breadcrumb struct {
	Name string
	URL  string
}

Breadcrumb represents a navigation breadcrumb entry.

type ControllerOptions

type ControllerOptions struct {
	// Store is the statsstore instance used for all visitor queries.
	Store statsstore.StoreInterface

	// Layout renders the full HTML page. Required.
	Layout LayoutInterface

	// HomeURL is the URL for the admin home page (e.g. "/admin").
	HomeURL string

	// WebsiteUrl is the public site URL.
	WebsiteUrl string

	// BaseURL is the base URL for the stats admin (e.g. "/admin/stats").
	// Replaces the old internal/links dependency.
	BaseURL string

	// CountryNameByIso2 maps an ISO2 code to a human-readable country name.
	// Optional; when nil, raw ISO2 codes are displayed.
	CountryNameByIso2 func(iso2Code string) (string, error)

	// AuthUserID returns the authenticated user ID from the request, or ""
	// when unauthenticated. When nil, auth checks are skipped.
	AuthUserID func(r *http.Request) string

	// FlashError renders a flash error message and returns the redirect
	// response body. When nil, controllers fall back to http.Redirect.
	FlashError func(w http.ResponseWriter, r *http.Request, message string, redirectURL string, delaySeconds int) string

	// Logger is used for internal logging. Defaults to slog.Default().
	Logger *slog.Logger
}

ControllerOptions contains the dependencies and configuration for creating an admin controller. It extends the original statsstore admin options with optional callbacks for auth, flash messages, and base URL configuration so the package remains self-contained and reusable by any project.

func (ControllerOptions) CountryName added in v1.25.0

func (o ControllerOptions) CountryName(iso2 string) string

CountryName resolves an ISO2 code to a human-readable country name using the CountryNameByIso2 callback. Returns the raw code when the callback is nil or returns an error.

type CountEntry added in v1.25.0

type CountEntry struct {
	Label string
	Count int64
}

CountEntry is a generic (label, count) pair used for top-N breakdowns.

func AggregateCounts added in v1.25.0

func AggregateCounts(visitors []VisitorLike, extract func(v VisitorLike) string) []CountEntry

AggregateCounts reduces a visitor slice to a frequency map keyed by the provided extractor. Empty labels are grouped under "—".

func TopN added in v1.25.0

func TopN(in []CountEntry, n int) []CountEntry

TopN returns at most n entries from a sorted slice.

type CountryNameResolver added in v1.25.0

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

CountryNameResolver wraps a CountryNameByIso2 callback with a simple pass-through cache. It is safe for concurrent use; the lookup runs once per resolver instance.

func NewCountryNameResolver added in v1.25.0

func NewCountryNameResolver(lookup func(iso2Code string) (string, error)) *CountryNameResolver

NewCountryNameResolver returns a fresh resolver bound to the given callback. If the callback is nil, Name always returns the raw code.

func (*CountryNameResolver) Name added in v1.25.0

func (r *CountryNameResolver) Name(_ context.Context, iso2 string) string

Name returns the human-readable country name for an ISO2 code, falling back to the code itself when unknown or when no lookup callback is configured.

type FakeLayout added in v1.25.0

type FakeLayout struct {
	Title      string
	Body       string
	Scripts    []string
	ScriptURLs []string
	Styles     []string
	StyleURLs  []string
}

FakeLayout implements LayoutInterface for testing. It captures all Set* calls and returns a fixed string from Render.

func (*FakeLayout) Render added in v1.25.0

func (*FakeLayout) SetBody added in v1.25.0

func (l *FakeLayout) SetBody(body string)

func (*FakeLayout) SetCountryNameByIso2 added in v1.25.0

func (l *FakeLayout) SetCountryNameByIso2(func(string) (string, error))

func (*FakeLayout) SetScriptURLs added in v1.25.0

func (l *FakeLayout) SetScriptURLs(urls []string)

func (*FakeLayout) SetScripts added in v1.25.0

func (l *FakeLayout) SetScripts(scripts []string)

func (*FakeLayout) SetStyleURLs added in v1.25.0

func (l *FakeLayout) SetStyleURLs(styles []string)

func (*FakeLayout) SetStyles added in v1.25.0

func (l *FakeLayout) SetStyles(styles []string)

func (*FakeLayout) SetTitle added in v1.25.0

func (l *FakeLayout) SetTitle(title string)

type LayoutInterface

type LayoutInterface interface {
	SetTitle(title string)
	SetScriptURLs(scripts []string)
	SetScripts(scripts []string)
	SetStyleURLs(styles []string)
	SetStyles(styles []string)
	SetBody(string)
	// SetCountryNameByIso2 provides country lookup helpers used by the admin UI.
	SetCountryNameByIso2(func(iso2Code string) (string, error))
	Render(w http.ResponseWriter, r *http.Request) string
}

LayoutInterface defines the layout methods needed by controllers. Consumers implement this to wrap admin pages in their own chrome.

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

Links builds stats admin URLs from a configured base URL. It mutates the passed params map by setting the controller key; callers should pass a fresh map each time.

func NewLinks(baseURL string) *Links

NewLinks returns a URL builder bound to the given base URL. If baseURL is empty, "/" is used as a safe default.

func (*Links) Base added in v1.25.0

func (l *Links) Base() string

Base returns the configured base URL.

func (*Links) Dashboard added in v1.25.0

func (l *Links) Dashboard(params map[string]string) string

func (*Links) IPDetails added in v1.25.0

func (l *Links) IPDetails(params map[string]string) string

func (*Links) Sessions added in v1.25.0

func (l *Links) Sessions(params map[string]string) string

func (*Links) Settings added in v1.25.0

func (l *Links) Settings(params map[string]string) string

func (*Links) Visitors added in v1.25.0

func (l *Links) Visitors(params map[string]string) string

type PeriodBounds added in v1.25.0

type PeriodBounds struct {
	From  string // inclusive, "YYYY-MM-DD HH:MM:SS"
	To    string // inclusive
	Label string
}

PeriodBounds holds the created_at >= / <= bounds for a selected period.

func ResolvePeriod added in v1.25.0

func ResolvePeriod(period string) PeriodBounds

ResolvePeriod maps a period identifier to concrete created_at bounds. Unknown or empty values fall back to the default period.

type VisitorLike added in v1.25.0

type VisitorLike interface {
	GetPath() string
	GetCountry() string
	GetUserBrowser() string
	GetUserOs() string
	GetUserDeviceType() string
	GetIpAddress() string
	GetCreatedAt() string
	GetBot() string
	GetThreat() string
}

VisitorLike is the minimal subset of statsstore.VisitorInterface used by aggregation helpers. The real interface satisfies it structurally.

Jump to

Keyboard shortcuts

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