userdb

package
v2.16.1 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2026 License: GPL-3.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MappingTypeID         = "id"
	MappingTypeValue      = "value"
	MappingTypeData       = "data"
	MatchTypeExact        = "exact"
	MatchTypePartial      = "partial"
	MatchTypeRegex        = "regex"
	LegacyMappingTypeUID  = "uid"
	LegacyMappingTypeText = "text"
)

Variables

View Source
var (
	// ErrProfileNotFound is returned when a profile lookup matches no row.
	ErrProfileNotFound = errors.New("profile not found")
	// ErrLastProfileAdmin is returned when an operation would remove the
	// final administrator profile.
	ErrLastProfileAdmin = errors.New("cannot remove the last admin profile")
)
View Source
var ErrConnDrainTimeout = errors.New("timed out waiting for user database queries to finish")

ErrConnDrainTimeout is returned when queries are still running after the connection pool has been closed and the drain deadline has passed.

View Source
var ErrInvalidAuthToken = errors.New("auth token must not contain ':'")

ErrInvalidAuthToken rejects ':' in auth tokens (AAD uses `<token>:ws`; also enforced by SQL CHECK).

View Source
var ErrLastClientAdmin = errors.New("cannot delete the last admin client")

ErrLastClientAdmin is returned when deleting the final admin client.

View Source
var ErrNullSQL = errors.New("UserDB is not connected")

Functions

func MappingsFromConfig added in v2.15.0

func MappingsFromConfig(cfg *config.Instance) []database.Mapping

MappingsFromConfig converts the file-based mappings loaded into config into the database.Mapping shape used for matching and API responses. The returned mappings are always enabled and carry no database ID, since they originate from the mappings folder rather than UserDB.

func NormalizeID

func NormalizeID(uid string) string

Types

type UserDB

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

func OpenUserDB

func OpenUserDB(ctx context.Context, pl platforms.Platform) (*UserDB, error)

func (*UserDB) ActivateProfile added in v2.16.0

func (db *UserDB) ActivateProfile(profileID string, lastUsedAt int64) error

ActivateProfile atomically records profile use and persists it as active.

func (*UserDB) AddHistory

func (db *UserDB) AddHistory(entry *database.HistoryEntry) error

func (*UserDB) AddInboxMessage added in v2.8.0

func (db *UserDB) AddInboxMessage(msg *database.InboxMessage) (*database.InboxMessage, error)

func (*UserDB) AddMapping

func (db *UserDB) AddMapping(m *database.Mapping) error

func (*UserDB) AddMediaHistory added in v2.7.0

func (db *UserDB) AddMediaHistory(entry *database.MediaHistoryEntry) (int64, error)

AddMediaHistory adds a new media history entry and returns the DBID.

func (*UserDB) Allocate

func (db *UserDB) Allocate() error

func (*UserDB) BackfillMediaHistoryUUIDs added in v2.16.0

func (db *UserDB) BackfillMediaHistoryUUIDs() (int64, error)

BackfillMediaHistoryUUIDs assigns stable session UUIDs to legacy MediaHistory rows written before UUIDs existed. Existing timestamps remain unchanged.

func (*UserDB) Backup added in v2.15.0

func (db *UserDB) Backup(reason string, manual bool) (database.BackupInfo, error)

func (*UserDB) BackupForTransfer added in v2.16.0

func (db *UserDB) BackupForTransfer(
	ctx context.Context, reason string,
) (database.BackupInfo, func() error, error)

BackupForTransfer creates a validated portable snapshot without paired-client credentials. Cleanup owns the private temporary directory and is safe to call more than once.

func (*UserDB) CleanupHistory added in v2.7.0

func (db *UserDB) CleanupHistory(retentionDays int) (int64, error)

func (*UserDB) CleanupMediaHistory added in v2.7.0

func (db *UserDB) CleanupMediaHistory(retentionDays int, requireSynced bool) (int64, error)

CleanupMediaHistory removes media history older than the retention period. When requireSynced is true, only server-acknowledged versions are removed.

func (*UserDB) ClearCorruptMarker added in v2.15.0

func (db *UserDB) ClearCorruptMarker() error

func (*UserDB) Close

func (db *UserDB) Close() error

func (*UserDB) CloseHangingMediaHistory added in v2.7.0

func (db *UserDB) CloseHangingMediaHistory() error

CloseHangingMediaHistory closes any media history entries left open from unclean shutdowns. It sets EndTime = StartTime + PlayTime for entries where EndTime is NULL.

func (*UserDB) CloseMediaHistory added in v2.7.0

func (db *UserDB) CloseMediaHistory(dbid int64, endTime time.Time, playTime int) error

CloseMediaHistory finalizes a media history entry with end time and final play time.

func (*UserDB) CountClients added in v2.11.0

func (db *UserDB) CountClients() (int, error)

func (*UserDB) CreateClient added in v2.11.0

func (db *UserDB) CreateClient(c *database.Client) error

func (*UserDB) CreateProfile added in v2.16.0

func (db *UserDB) CreateProfile(p *database.Profile) error

func (*UserDB) DeleteAllInboxMessages added in v2.8.0

func (db *UserDB) DeleteAllInboxMessages() (int64, error)

func (*UserDB) DeleteClient added in v2.11.0

func (db *UserDB) DeleteClient(clientID string) error

func (*UserDB) DeleteDeviceState added in v2.16.0

func (db *UserDB) DeleteDeviceState(key string) error

func (*UserDB) DeleteInboxMessage added in v2.8.0

func (db *UserDB) DeleteInboxMessage(id int64) error

func (*UserDB) DeleteMapping

func (db *UserDB) DeleteMapping(id int64) error

func (*UserDB) DeleteMediaUserData added in v2.15.0

func (db *UserDB) DeleteMediaUserData(systemID, path string) error

DeleteMediaUserData removes the user-data row for (SystemID, Path). Deleting a row that does not exist is not an error.

func (*UserDB) DeleteProfile added in v2.16.0

func (db *UserDB) DeleteProfile(profileID string) error

DeleteProfile removes a profile. If the profile is the device's active profile, the active-profile device state is cleared in the same transaction.

func (*UserDB) EnsureRecentBackup added in v2.15.0

func (db *UserDB) EnsureRecentBackup(maxAge time.Duration) (database.BackupInfo, bool, error)

func (*UserDB) GetAllMappings

func (db *UserDB) GetAllMappings() ([]database.Mapping, error)

func (*UserDB) GetClientByToken added in v2.11.0

func (db *UserDB) GetClientByToken(authToken string) (*database.Client, error)

func (*UserDB) GetDBPath

func (db *UserDB) GetDBPath() string

func (*UserDB) GetDeviceState added in v2.16.0

func (db *UserDB) GetDeviceState(key string) (value string, found bool, err error)

GetDeviceState returns the value for key and whether it exists.

func (*UserDB) GetEnabledMappings

func (db *UserDB) GetEnabledMappings() ([]database.Mapping, error)

func (*UserDB) GetHistory

func (db *UserDB) GetHistory(lastID int64) ([]database.HistoryEntry, error)

func (*UserDB) GetInboxMessages added in v2.8.0

func (db *UserDB) GetInboxMessages() ([]database.InboxMessage, error)

func (*UserDB) GetLatestMediaHistory added in v2.14.0

func (db *UserDB) GetLatestMediaHistory() (database.MediaHistoryEntry, bool, error)

GetLatestMediaHistory retrieves the most recent media history entry with no enrichment.

func (*UserDB) GetMapping

func (db *UserDB) GetMapping(id int64) (database.Mapping, error)

func (*UserDB) GetMediaHistory added in v2.7.0

func (db *UserDB) GetMediaHistory(systemIDs []string, lastID int64, limit int) ([]database.MediaHistoryEntry, error)

GetMediaHistory retrieves media history entries with pagination and optional system filtering.

func (*UserDB) GetMediaHistoryIdentityBackfillBatch added in v2.16.1

func (db *UserDB) GetMediaHistoryIdentityBackfillBatch(
	afterDBID int64, policyVersion int, limit int,
) ([]database.MediaHistoryEntry, error)

GetMediaHistoryIdentityBackfillBatch returns legacy history rows whose scanner identity is absent or older than policyVersion. Future-policy rows are never selected for downgrade.

func (*UserDB) GetMediaHistorySyncBatch added in v2.16.0

func (db *UserDB) GetMediaHistorySyncBatch(
	after time.Time, afterDBID int64, limit int,
) ([]database.MediaHistoryEntry, error)

GetMediaHistorySyncBatch returns unsynced rows after the local (after, afterDBID) cursor in (UpdatedAt, DBID) order. Mutations clear SyncedAt, so acknowledged rows do not repeat and unreliable-clock rows remain eligible regardless of the server's timestamp watermark. Rows without a session UUID are excluded; startup backfills legacy rows first.

func (*UserDB) GetMediaHistoryTop added in v2.10.0

func (db *UserDB) GetMediaHistoryTop(
	systemIDs []string, since *time.Time, limit int,
) ([]database.MediaHistoryTopEntry, error)

GetMediaHistoryTop returns aggregated media history grouped by SystemID+MediaName, sorted by total play time descending.

func (*UserDB) GetMediaUserData added in v2.15.0

func (db *UserDB) GetMediaUserData(systemID, path string) (database.MediaUserData, bool, error)

GetMediaUserData returns the user-data row for a media path. The bool is false when no row exists for the (systemID, path) key, in which case the media has no favourite or launcher-override intent recorded.

func (*UserDB) GetProfile added in v2.16.0

func (db *UserDB) GetProfile(profileID string) (*database.Profile, error)

func (*UserDB) GetProfileBySwitchID added in v2.16.0

func (db *UserDB) GetProfileBySwitchID(switchID string) (*database.Profile, error)

func (*UserDB) GetSupportedZapLinkHosts added in v2.8.0

func (db *UserDB) GetSupportedZapLinkHosts() ([]string, error)

func (*UserDB) GetZapLinkCache

func (db *UserDB) GetZapLinkCache(url string) (string, error)

func (*UserDB) GetZapLinkHost

func (db *UserDB) GetZapLinkHost(host string) (found, zapScript bool, err error)

func (*UserDB) HealTimestamps added in v2.7.0

func (db *UserDB) HealTimestamps(bootUUID string, trueBootTime time.Time) (int64, error)

HealTimestamps corrects timestamps for records created with unreliable clocks (MiSTer boot without NTP). When NTP syncs, this reconstructs correct timestamps using: TrueStartTime = TrueBootTime + MonotonicStart

func (*UserDB) IntegrityReport added in v2.15.0

func (db *UserDB) IntegrityReport() []string

func (*UserDB) IsMarkedCorrupt added in v2.15.0

func (db *UserDB) IsMarkedCorrupt() bool

func (*UserDB) ListBackups added in v2.15.0

func (db *UserDB) ListBackups() ([]database.BackupInfo, error)

func (*UserDB) ListClients added in v2.11.0

func (db *UserDB) ListClients() ([]database.Client, error)

func (*UserDB) ListMediaUserData added in v2.15.0

func (db *UserDB) ListMediaUserData() ([]database.MediaUserData, error)

ListMediaUserData returns every user-data row, used by the reindex re-apply step to re-materialize the media.db projection.

func (*UserDB) ListProfiles added in v2.16.0

func (db *UserDB) ListProfiles() ([]database.Profile, error)

func (*UserDB) MarkCorrupt added in v2.15.0

func (db *UserDB) MarkCorrupt(reason string)

func (*UserDB) MarkMediaHistorySynced added in v2.16.0

func (db *UserDB) MarkMediaHistorySynced(refs []database.MediaHistorySyncRef, syncedAt time.Time) error

MarkMediaHistorySynced stamps SyncedAt only when each row still matches the uploaded version. Concurrent mutations advance UpdatedAt and remain unsynced.

func (*UserDB) MigrateUp

func (db *UserDB) MigrateUp() error

func (*UserDB) NoteCorruption added in v2.15.0

func (db *UserDB) NoteCorruption(err error) bool

func (*UserDB) Open

func (db *UserDB) Open() error

func (*UserDB) PruneExpiredZapLinkHosts added in v2.8.0

func (db *UserDB) PruneExpiredZapLinkHosts(olderThan time.Duration) (int64, error)

func (*UserDB) RecoverFromCorruption added in v2.15.0

func (db *UserDB) RecoverFromCorruption() (database.RestoreInfo, error)

func (*UserDB) ReplaceAllClients added in v2.16.0

func (db *UserDB) ReplaceAllClients(clients []database.Client) error

ReplaceAllClients atomically replaces every paired client row. Device backup restore uses this to carry the destination's paired clients across a restored user database, since portable snapshots are created without client rows.

func (*UserDB) ResetMediaHistorySyncAfter added in v2.16.0

func (db *UserDB) ResetMediaHistorySyncAfter(watermark *time.Time) error

ResetMediaHistorySyncAfter clears local acknowledgements newer than the server watermark so restored or reset server state is uploaded again. A nil watermark means the server has no sessions and resets every local row.

func (*UserDB) RestoreBackup added in v2.15.0

func (db *UserDB) RestoreBackup(name string) (database.RestoreInfo, error)

func (*UserDB) SetDeviceState added in v2.16.0

func (db *UserDB) SetDeviceState(key, value string) error

func (*UserDB) SetMediaUserFavorite added in v2.15.0

func (db *UserDB) SetMediaUserFavorite(systemID, path string, favorite bool) error

SetMediaUserFavorite records (or clears) the favourite intent for a media path without disturbing any launcher override on the same row. The write is a column-scoped upsert plus a conditional delete, run in one transaction so two concurrent edits to the same path (e.g. a favourite toggle and a launcher override) cannot read-modify-write over each other.

func (*UserDB) SetMediaUserLauncherOverride added in v2.15.0

func (db *UserDB) SetMediaUserLauncherOverride(systemID, path, launcherID string) error

SetMediaUserLauncherOverride records (or clears, when launcherID is empty) the launcher-override intent for a media path without disturbing the favourite flag on the same row. See SetMediaUserFavorite for the concurrency guarantee.

func (*UserDB) SetMediaUserSnapshot added in v2.16.0

func (db *UserDB) SetMediaUserSnapshot(systemID, path, mediaName string, tags []string) error

SetMediaUserSnapshot records a successfully resolved scanner identity snapshot on an existing user-data row. It never inserts: a snapshot without user intent (favourite/override) is meaningless. Empty tags are significant and replace stale tags; callers must skip this method when lookup fails.

func (*UserDB) SetSQLForTesting

func (db *UserDB) SetSQLForTesting(ctx context.Context, sqlDB *sql.DB, platform platforms.Platform) error

SetSQLForTesting allows injection of a sql.DB instance for testing purposes. This method should only be used in tests to set up in-memory databases.

func (*UserDB) SumMediaPlayTimeForDay added in v2.15.0

func (db *UserDB) SumMediaPlayTimeForDay(dayStart time.Time) (int64, error)

SumMediaPlayTimeForDay returns the total seconds of completed play-time that overlaps with the day starting at dayStart. Sessions that span midnight are pro-rated: only the portion after dayStart is counted. The currently-active session (EndTime IS NULL) is excluded; callers add it separately.

func (*UserDB) SumMediaPlayTimeForDayByProfile added in v2.16.0

func (db *UserDB) SumMediaPlayTimeForDayByProfile(dayStart time.Time, profileID string) (int64, error)

SumMediaPlayTimeForDayByProfile is SumMediaPlayTimeForDay scoped to history attributed to a single profile. History with no profile (the shared profile) is counted by SumMediaPlayTimeForDay, which sums all rows: shared limits are device-level, so deactivating a profile must not grant a fresh daily allowance.

func (*UserDB) Truncate

func (db *UserDB) Truncate() error

func (*UserDB) UnsafeGetSQLDb

func (db *UserDB) UnsafeGetSQLDb() *sql.DB

func (*UserDB) UpdateClientLastSeen added in v2.11.0

func (db *UserDB) UpdateClientLastSeen(authToken string, lastSeenAt int64) error

func (*UserDB) UpdateMapping

func (db *UserDB) UpdateMapping(id int64, m *database.Mapping) error

func (*UserDB) UpdateMediaHistoryIdentity added in v2.16.0

func (db *UserDB) UpdateMediaHistoryIdentity(dbid int64, identity *database.MediaIdentity) (bool, error)

UpdateMediaHistoryIdentity stores a complete scanner identity snapshot and reports whether this policy version changed the history row.

func (*UserDB) UpdateMediaHistoryTime added in v2.7.0

func (db *UserDB) UpdateMediaHistoryTime(dbid int64, playTime int) error

UpdateMediaHistoryTime updates only the PlayTime for currently playing media.

func (*UserDB) UpdateProfile added in v2.16.0

func (db *UserDB) UpdateProfile(p *database.Profile) error

func (*UserDB) UpdateZapLinkCache

func (db *UserDB) UpdateZapLinkCache(url, zapscript string) error

func (*UserDB) UpdateZapLinkHost

func (db *UserDB) UpdateZapLinkHost(host string, zapscript int) error

func (*UserDB) UpsertMediaUserData added in v2.15.0

func (db *UserDB) UpsertMediaUserData(data *database.MediaUserData) error

UpsertMediaUserData inserts or updates the user-data row for (SystemID, Path). CreatedAt is set on insert only; UpdatedAt is set on every write. A row with no favourite and no launcher override carries no user intent, so it is deleted rather than persisted (keeping ListMediaUserData and the backfill guard honest).

func (*UserDB) Vacuum

func (db *UserDB) Vacuum() error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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