Documentation
¶
Index ¶
- Variables
- type AgentFilter
- type AgentRepository
- type AuditFilter
- type AuditRepository
- type DashboardRepository
- type DashboardStats
- type DayJobActivity
- type DaySizeActivity
- type DestinationFilter
- type DestinationRepository
- type JobDestinationWithName
- type JobFilter
- type JobRepository
- type JobWithNames
- type ListOptions
- type NotificationRepository
- type OIDCProviderRepository
- type PasswordResetTokenRepository
- type PolicyDestinationWithName
- type PolicyRepository
- type RefreshTokenRepository
- type SettingsRepository
- type SnapshotRepository
- type SnapshotWithNames
- type UserRepository
Constants ¶
This section is empty.
Variables ¶
var ErrConflict = errors.New("record already exists")
ErrConflict is returned when an insert or update violates a unique constraint, for example when registering a user with an email that already exists.
var ErrNotFound = errors.New("record not found")
ErrNotFound is returned by repository methods when the requested record does not exist in the database. Callers should check for this error explicitly using errors.Is to distinguish missing records from other database errors.
user, err := repo.GetByID(ctx, id)
if errors.Is(err, repositories.ErrNotFound) {
handle not found
}
Functions ¶
This section is empty.
Types ¶
type AgentFilter ¶
type AgentFilter struct {
Search string // case-insensitive substring match on name
Status string // exact match on status (e.g. "online", "offline")
}
AgentFilter restricts results returned by AgentRepository.ListFiltered. Zero values mean "no filter" for that field.
type AgentRepository ¶
type AgentRepository interface {
Create(ctx context.Context, agent *db.Agent) error
GetByID(ctx context.Context, id uuid.UUID) (*db.Agent, error)
GetByHostname(ctx context.Context, hostname string) (*db.Agent, error)
Update(ctx context.Context, agent *db.Agent) error
UpdateStatus(ctx context.Context, id uuid.UUID, status string, lastSeenAt time.Time) error
Delete(ctx context.Context, id uuid.UUID) error
List(ctx context.Context, opts ListOptions) ([]db.Agent, int64, error)
ListFiltered(ctx context.Context, filter AgentFilter, opts ListOptions) ([]db.Agent, int64, error)
// TotalCount returns the count of all non-deleted agents in the database.
// Used by telemetry to report the registered agent count regardless of
// whether agents are currently connected.
TotalCount(ctx context.Context) int
}
func NewAgentRepository ¶
func NewAgentRepository(db *gorm.DB) AgentRepository
NewAgentRepository returns an AgentRepository backed by the provided *gorm.DB.
type AuditFilter ¶
type AuditFilter struct {
UserID *uuid.UUID
Action string // prefix match: "policy." matches all policy events
ResourceType string
From *time.Time
To *time.Time
}
AuditFilter restricts the result set returned by AuditRepository.List. Zero values mean "no filter" for that field.
type AuditRepository ¶
type AuditRepository interface {
Create(ctx context.Context, entry *db.AuditLog) error
List(ctx context.Context, filter AuditFilter, opts ListOptions) ([]db.AuditLog, int64, error)
}
AuditRepository provides append-only access to the audit_log table. Records are never updated or deleted — only created and listed.
func NewAuditRepository ¶
func NewAuditRepository(db *gorm.DB) AuditRepository
NewAuditRepository returns an AuditRepository backed by the provided *gorm.DB.
type DashboardRepository ¶
type DashboardRepository interface {
GetStats(ctx context.Context) (*DashboardStats, error)
}
DashboardRepository computes aggregated statistics for the dashboard. All queries are read-only and do not modify any data.
func NewDashboardRepository ¶
func NewDashboardRepository(db *gorm.DB) DashboardRepository
NewDashboardRepository returns a DashboardRepository backed by the provided *gorm.DB.
type DashboardStats ¶
type DashboardStats struct {
// Agent counts
AgentsTotal int64
AgentsOnline int64
// Policy counts
PoliciesTotal int64
PoliciesActive int64
// Job counts for today (UTC)
JobsTodayTotal int64
JobsTodaySucceeded int64
JobsTodayFailed int64
// Snapshot totals (all time)
SnapshotsTotal int64
SnapshotsTotalSize int64 // sum of size_bytes
// Activity over the last 7 days (index 0 = oldest, index 6 = today)
JobActivity []DayJobActivity
SizeActivity []DaySizeActivity
}
DashboardStats holds all aggregated data needed by the dashboard endpoint. It is computed in a single repository call that executes several lightweight SQL queries in sequence — fast because all are index-backed COUNT/SUM queries.
type DayJobActivity ¶
DayJobActivity holds the succeeded and failed job counts for a single calendar day.
type DaySizeActivity ¶
DaySizeActivity holds the total bytes backed up for a single calendar day, derived from snapshot records created on that day.
type DestinationFilter ¶
type DestinationFilter struct {
Search string // case-insensitive substring match on name
}
DestinationFilter restricts results returned by DestinationRepository.ListFiltered. Zero values mean "no filter" for that field.
type DestinationRepository ¶
type DestinationRepository interface {
Create(ctx context.Context, destination *db.Destination) error
GetByID(ctx context.Context, id uuid.UUID) (*db.Destination, error)
Update(ctx context.Context, destination *db.Destination) error
// UpdateRepoSize refreshes only the cached restic repository size and its
// timestamp, leaving all other destination fields untouched.
UpdateRepoSize(ctx context.Context, id uuid.UUID, sizeBytes int64, at time.Time) error
Delete(ctx context.Context, id uuid.UUID) error
List(ctx context.Context, opts ListOptions) ([]db.Destination, int64, error)
ListFiltered(ctx context.Context, filter DestinationFilter, opts ListOptions) ([]db.Destination, int64, error)
}
func NewDestinationRepository ¶
func NewDestinationRepository(db *gorm.DB) DestinationRepository
NewDestinationRepository returns a DestinationRepository backed by the provided *gorm.DB.
type JobDestinationWithName ¶
type JobDestinationWithName struct {
db.JobDestination
DestinationName string
}
JobDestinationWithName extends db.JobDestination with the destination's display name, resolved via LEFT JOIN in ListDestinationsByJob. LEFT JOIN ensures rows survive even if the destination was deleted.
type JobFilter ¶
type JobFilter struct {
Status string // e.g. "pending", "running", "succeeded", "failed", "cancelled"
Type string // e.g. "backup", "restore"
}
JobFilter restricts the result set returned by JobRepository.ListFiltered. Zero values mean "no filter" for that field.
type JobRepository ¶
type JobRepository interface {
Create(ctx context.Context, job *db.Job) error
GetByID(ctx context.Context, id uuid.UUID) (*db.Job, error)
GetByIDWithDetails(ctx context.Context, id uuid.UUID) (*JobWithNames, []JobDestinationWithName, []db.JobLog, error)
Update(ctx context.Context, job *db.Job) error
UpdateStatus(ctx context.Context, id uuid.UUID, status string, startedAt *time.Time, endedAt *time.Time, errMsg string) error
FailRunningJobsForAgent(ctx context.Context, agentID uuid.UUID, errMsg string) (int64, error)
List(ctx context.Context, opts ListOptions) ([]JobWithNames, int64, error)
ListFiltered(ctx context.Context, filter JobFilter, opts ListOptions) ([]JobWithNames, int64, error)
ListByType(ctx context.Context, jobType string, opts ListOptions) ([]JobWithNames, int64, error)
ListByPolicy(ctx context.Context, policyID uuid.UUID, opts ListOptions) ([]JobWithNames, int64, error)
ListByAgent(ctx context.Context, agentID uuid.UUID, opts ListOptions) ([]JobWithNames, int64, error)
HasPendingJob(ctx context.Context, policyID uuid.UUID) (bool, error)
// JobDestination
CreateDestination(ctx context.Context, jd *db.JobDestination) error
ListDestinationsByJob(ctx context.Context, jobID uuid.UUID) ([]JobDestinationWithName, error)
UpdateDestinationStatus(ctx context.Context, jobID uuid.UUID, destID uuid.UUID, status string, startedAt *time.Time, endedAt *time.Time, snapshotID string, sizeBytes int64, errMsg string) error
// JobLog
BulkCreateLogs(ctx context.Context, logs []db.JobLog) error
GetLogs(ctx context.Context, jobID uuid.UUID) ([]db.JobLog, error)
}
func NewJobRepository ¶
func NewJobRepository(db *gorm.DB) JobRepository
NewJobRepository returns a JobRepository backed by the provided *gorm.DB.
type JobWithNames ¶
JobWithNames extends db.Job with denormalised policy and agent names. Populated via LEFT JOIN in the List* methods so the API can return display-ready responses without per-row lookups. LEFT JOIN ensures jobs whose policy or agent has been soft-deleted still appear (names = "").
type ListOptions ¶
ListOptions contains common pagination and filtering options for list queries. SortBy/SortDesc are optional; repositories that support sorting map SortBy to a whitelisted column (unknown/empty values fall back to the default order). Repositories that don't support sorting simply ignore these fields.
type NotificationRepository ¶
type NotificationRepository interface {
Create(ctx context.Context, notification *db.Notification) error
GetByID(ctx context.Context, id uuid.UUID) (*db.Notification, error)
MarkAsRead(ctx context.Context, id uuid.UUID) error
MarkAllAsRead(ctx context.Context, userID uuid.UUID) error
Delete(ctx context.Context, id uuid.UUID) error
ListByUser(ctx context.Context, userID uuid.UUID, opts ListOptions) ([]db.Notification, int64, error)
DeleteReadOlderThan(ctx context.Context, t time.Time) error
// CreateDelivery inserts a new delivery row for the given channel type.
CreateDelivery(ctx context.Context, d *db.NotificationDelivery) error
// UpdateDelivery persists a delivery row after a send attempt (status,
// attempts, last_error, next_retry_at are the fields typically changed).
UpdateDelivery(ctx context.Context, d *db.NotificationDelivery) error
// ListPendingDeliveries returns up to limit delivery rows whose status is
// "pending" and whose next_retry_at is at or before `before`.
// Used by the retrier to find work to process.
ListPendingDeliveries(ctx context.Context, before time.Time, limit int) ([]*db.NotificationDelivery, error)
// ListDeliveriesByStatus returns delivery rows filtered by status, ordered
// newest first. Used by the admin queue visibility endpoint.
ListDeliveriesByStatus(ctx context.Context, status string, opts ListOptions) ([]db.NotificationDelivery, int64, error)
}
func NewNotificationRepository ¶
func NewNotificationRepository(db *gorm.DB) NotificationRepository
NewNotificationRepository returns a NotificationRepository backed by the provided *gorm.DB.
type OIDCProviderRepository ¶
type OIDCProviderRepository interface {
Create(ctx context.Context, provider *db.OIDCProvider) error
GetByID(ctx context.Context, id uuid.UUID) (*db.OIDCProvider, error)
List(ctx context.Context) ([]*db.OIDCProvider, error)
ListEnabled(ctx context.Context) ([]*db.OIDCProvider, error)
Update(ctx context.Context, provider *db.OIDCProvider) error
Delete(ctx context.Context, id uuid.UUID) error
}
func NewOIDCProviderRepository ¶
func NewOIDCProviderRepository(db *gorm.DB) OIDCProviderRepository
NewOIDCProviderRepository returns an OIDCProviderRepository backed by the provided *gorm.DB.
type PasswordResetTokenRepository ¶
type PasswordResetTokenRepository interface {
Create(ctx context.Context, token *db.PasswordResetToken) error
// GetUnusedByHash returns an unused token matching the hash. Expiry is
// checked by the caller in Go (timezone-safe), mirroring refresh tokens.
// Returns ErrNotFound if no unused token matches.
GetUnusedByHash(ctx context.Context, hash string) (*db.PasswordResetToken, error)
MarkUsed(ctx context.Context, id uuid.UUID) error
// DeleteByUserID removes all reset tokens for a user, invalidating any
// outstanding links when a new reset is requested.
DeleteByUserID(ctx context.Context, userID uuid.UUID) error
}
func NewPasswordResetTokenRepository ¶
func NewPasswordResetTokenRepository(db *gorm.DB) PasswordResetTokenRepository
NewPasswordResetTokenRepository returns a PasswordResetTokenRepository backed by the provided *gorm.DB.
type PolicyDestinationWithName ¶
type PolicyDestinationWithName struct {
db.PolicyDestination
DestinationName string
}
PolicyDestinationWithName extends db.PolicyDestination with the denormalised destination name resolved via JOIN. Deleted destinations are excluded from all queries that return this type.
type PolicyRepository ¶
type PolicyRepository interface {
Create(ctx context.Context, policy *db.Policy) error
GetByID(ctx context.Context, id uuid.UUID) (*db.Policy, error)
// GetByIDWithDestinations retrieves a policy together with its associated
// PolicyDestination records. The destinations are returned as a separate
// slice rather than embedded in the Policy struct, because GORM cannot
// auto-resolve UUID-typed foreign keys. Callers iterate the slice directly.
// Destinations that have been deleted are excluded automatically.
GetByIDWithDestinations(ctx context.Context, id uuid.UUID) (*db.Policy, []PolicyDestinationWithName, error)
Update(ctx context.Context, policy *db.Policy) error
Delete(ctx context.Context, id uuid.UUID) error
List(ctx context.Context, opts ListOptions) ([]db.Policy, int64, error)
ListByAgent(ctx context.Context, agentID uuid.UUID) ([]db.Policy, error)
ListEnabled(ctx context.Context) ([]db.Policy, error)
UpdateSchedule(ctx context.Context, id uuid.UUID, lastRunAt, nextRunAt time.Time) error
// ActivePoliciesCount returns the count of enabled, non-deleted policies.
// Used by telemetry.
ActivePoliciesCount(ctx context.Context) int
// PolicyDestination
AddDestination(ctx context.Context, pd *db.PolicyDestination) error
RemoveDestination(ctx context.Context, policyID, destinationID uuid.UUID) error
UpdateDestinationPriority(ctx context.Context, policyID, destinationID uuid.UUID, priority int) error
DeleteAllDestinations(ctx context.Context, policyID uuid.UUID) error
DeleteDestinationAssociations(ctx context.Context, destinationID uuid.UUID) error
// GetDestinations returns active (non-deleted) destination associations for a
// policy ordered by priority. Deleted destinations are excluded automatically.
GetDestinations(ctx context.Context, policyID uuid.UUID) ([]PolicyDestinationWithName, error)
}
func NewPolicyRepository ¶
func NewPolicyRepository(db *gorm.DB) PolicyRepository
NewPolicyRepository returns a PolicyRepository backed by the provided *gorm.DB.
type RefreshTokenRepository ¶
type RefreshTokenRepository interface {
Create(ctx context.Context, token *db.RefreshToken) error
GetByHash(ctx context.Context, hash string) (*db.RefreshToken, error)
DeleteByHash(ctx context.Context, hash string) error
Revoke(ctx context.Context, id uuid.UUID) error
RevokeAllForUser(ctx context.Context, userID uuid.UUID) error
DeleteExpired(ctx context.Context) error
}
func NewRefreshTokenRepository ¶
func NewRefreshTokenRepository(db *gorm.DB) RefreshTokenRepository
NewRefreshTokenRepository returns a RefreshTokenRepository backed by the provided *gorm.DB.
type SettingsRepository ¶
type SettingsRepository interface {
// Get retrieves a single setting by key. Returns ErrNotFound if absent.
Get(ctx context.Context, key string) (*db.Setting, error)
// Set creates or updates a setting (upsert semantics).
Set(ctx context.Context, key string, value db.EncryptedString) error
// GetMany retrieves multiple settings by key prefix (e.g. "smtp." returns
// all SMTP settings). Returns an empty slice if none match.
GetMany(ctx context.Context, prefix string) ([]db.Setting, error)
// Delete removes a setting. No-op if the key does not exist.
Delete(ctx context.Context, key string) error
}
SettingsRepository manages server configuration key-value pairs. It is the single point of access for the settings table — no other component should read or write settings directly.
func NewSettingsRepository ¶
func NewSettingsRepository(database *gorm.DB) SettingsRepository
NewSettingsRepository creates a new SettingsRepository backed by GORM.
type SnapshotRepository ¶
type SnapshotRepository interface {
Create(ctx context.Context, snapshot *db.Snapshot) error
GetByID(ctx context.Context, id uuid.UUID) (*db.Snapshot, error)
Delete(ctx context.Context, id uuid.UUID) error
DeleteBySnapshotID(ctx context.Context, snapshotID string) error
ExistsBySnapshotIDAndDestination(ctx context.Context, snapshotID string, destinationID uuid.UUID) (bool, error)
List(ctx context.Context, opts ListOptions) ([]SnapshotWithNames, int64, error)
ListByPolicy(ctx context.Context, policyID uuid.UUID, opts ListOptions) ([]SnapshotWithNames, int64, error)
ListByDestination(ctx context.Context, destinationID uuid.UUID, opts ListOptions) ([]SnapshotWithNames, int64, error)
}
func NewSnapshotRepository ¶
func NewSnapshotRepository(db *gorm.DB) SnapshotRepository
NewSnapshotRepository returns a SnapshotRepository backed by the provided *gorm.DB.
type SnapshotWithNames ¶
type SnapshotWithNames struct {
db.Snapshot
PolicyName string
DestinationName string
AgentID string
AgentName string
}
SnapshotWithNames extends db.Snapshot with denormalised display names resolved via JOIN. Used by list endpoints so the GUI does not need separate requests to resolve policy and destination names.
type UserRepository ¶
type UserRepository interface {
Create(ctx context.Context, user *db.User) error
GetByID(ctx context.Context, id uuid.UUID) (*db.User, error)
GetByEmail(ctx context.Context, email string) (*db.User, error)
GetByOIDC(ctx context.Context, provider, sub string) (*db.User, error)
Update(ctx context.Context, user *db.User) error
Delete(ctx context.Context, id uuid.UUID) error
List(ctx context.Context, opts ListOptions) ([]db.User, int64, error)
}
func NewUserRepository ¶
func NewUserRepository(db *gorm.DB) UserRepository
NewUserRepository returns a UserRepository backed by the provided *gorm.DB.