Help us shape the future of Go! Take the 2026 Go Developer Survey

store

package
v0.16.0 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package store holds typed repositories over the panel database.

Pattern for new repositories (other streams: devices, address books, ...):

  • one file per aggregate with a struct holding a db.Querier;
  • add a field to Store and construct it in build();
  • map driver errors with mapErr so callers only see ErrNotFound, ErrConflict and ErrReferenced;
  • timestamps go through toMs/fromMs (UTC unix milliseconds).

Use Store.Tx to run several repository calls atomically.

Index

Constants

View Source
const (
	BulkDelete     = "delete"
	BulkAddTags    = "add_tags"
	BulkRemoveTags = "remove_tags"
	BulkSetTags    = "set_tags"
)

Bulk entry actions.

View Source
const (
	OSWindows = "windows"
	OSMacOS   = "macos"
	OSLinux   = "linux"
	OSAndroid = "android"
	OSIOS     = "ios"
	OSOther   = "other"
)

OS families reported by the admin API (components.schemas.OsFamily).

View Source
const (
	RetentionLoginEvents        = "login_events"
	RetentionConnectionAudits   = "connection_audits"
	RetentionFileTransferAudits = "file_transfer_audits"
	RetentionAlarmAudits        = "alarm_audits"
	RetentionAdminAudit         = "admin_audit"
	RetentionPunchRequests      = "punch_requests"
)

Retention categories (PanelSettings.retention keys without "_days").

View Source
const (
	EmailCodeVerify        = "verify_email"
	EmailCodeLogin         = "login"
	EmailCodePasswordReset = "password_reset"
)

Email code purposes (email_codes.purpose).

View Source
const (
	LoginMethodPassword = "password"
	LoginMethodOIDC     = "oidc"
	LoginMethodWebAuth  = "webauth"
	LoginMethodPasskey  = "passkey"

	LoginSuccess = "success"
	LoginFailure = "failure"
)

Login methods and results (login_events.method / .result).

View Source
const (
	SettingBrandingWebClientURL   = "branding.web_client_url"
	SettingPasswordLoginEnabled   = "auth.password_login_enabled"
	SettingSessionIdleHours       = "auth.session_idle_hours"
	SettingSessionAbsoluteDays    = "auth.session_absolute_days"
	SettingClientTokenLifetimeH   = "auth.client_token_lifetime_hours"
	SettingRetentionLoginEvents   = "retention.login_events_days"
	SettingRetentionConnections   = "retention.connection_audits_days"
	SettingRetentionFileTransfers = "retention.file_transfer_audits_days"
	SettingRetentionAlarms        = "retention.alarm_audits_days"
	SettingRetentionAdminAudit    = "retention.admin_audit_days"
	SettingRetentionPunchRequests = "retention.punch_requests_days"
)

Panel settings keys managed by PATCH /settings (values are JSON). The branding title/welcome and auth.require_admin_2fa keys are in settings.go.

View Source
const (
	SettingBrandingTitle   = "branding.title"
	SettingBrandingWelcome = "branding.welcome_markdown"
	SettingRequireAdmin2FA = "auth.require_admin_2fa"
)

Well-known settings keys. Values are JSON.

View Source

AssetLogo is the panel_assets name of the branding logo.

View Source
const DefaultTagColor uint32 = 0xFF9E9E9E

DefaultTagColor is used for tags created implicitly (a peer or legacy blob referencing a tag name with no colour): Flutter ARGB 0xFF9E9E9E (grey).

View Source
const MaxAPITokensPerUser = 50

MaxAPITokensPerUser bounds the non-revoked api_tokens rows of one user.

View Source
const MaxAssetBytes = 256 << 10

MaxAssetBytes bounds a stored asset (CHECK in the schema too).

View Source
const MaxPasskeysPerUser = 20

MaxPasskeysPerUser bounds webauthn_credentials rows per user.

View Source
const MaxServerShareLinksPerUser = 100

MaxServerShareLinksPerUser bounds the non-revoked, non-expired links of one user.

View Source
const MaxTerminalShells = 10

MaxTerminalShells bounds the remembered terminal sessions per user and device.

View Source
const OAuthStateProcessing = "\x01processing"

OAuthStateProcessing is the result_error sentinel written while a callback is exchanging the code (claims the state so a second callback cannot run). Pollers treat it as "still pending"; it is never shown to users. The control-character prefix cannot occur in a real message (it is not NUL: PostgreSQL text cannot hold NUL bytes).

Variables

View Source
var (
	// ErrNotFound means the requested row does not exist (or is not active).
	ErrNotFound = errors.New("store: not found")
	// ErrConflict means a uniqueness constraint was violated.
	ErrConflict = errors.New("store: conflict")
	// ErrReferenced means a foreign key constraint was violated (missing
	// parent or a row still referenced with ON DELETE RESTRICT).
	ErrReferenced = errors.New("store: foreign key violation")
	// ErrInvalid means a CHECK constraint rejected the values.
	ErrInvalid = errors.New("store: invalid value")
)

Repository errors. Wrap-checked with errors.Is.

View Source
var DeviceSortKeys = []string{"rustdesk_id", "hostname", "alias", "os", "client_version", "last_seen_at", "created_at", "online"}

DeviceSortKeys are the accepted DeviceSearch.Sort values.

View Source
var ErrNoSecrets = errors.New("store: secrets-at-rest key not configured")

ErrNoSecrets is returned by repositories that store returnable secrets when the Store was built without WithSecrets.

View Source
var ErrRoleInUse = fmt.Errorf("%w: control role is referenced by connection rules", ErrReferenced)

ErrRoleInUse is returned (wrapping ErrReferenced) when deleting a control role that rules still reference: deleting it would silently switch those rules to the default role.

OSFamilies lists every valid family value.

RetentionDefaults are the retention days of categories without a stored setting (retention.<category>_days); 0 keeps rows forever.

Functions

func DecideACL added in v0.11.0

func DecideACL(rules []*ConnectionACL, s ACLSubject) (ACLDecision, *ConnectionACL)

DecideACL is the connection decision for s under rules (in priority order; disabled rules are skipped): the first rule matching both the user and the device decides. Without a match, owner access is allowed and everything else denied (default deny), or allowed when no rule is enabled at all.

func GetOr

func GetOr[T any](ctx context.Context, s *Settings, key string, def T) (T, error)

GetOr is Get with a default for unset keys.

func HourStart

func HourStart(t time.Time) time.Time

HourStart returns the start of the UTC hour containing t.

func NewUUID

func NewUUID() string

NewUUID returns a random RFC 4122 version-4 UUID in canonical form. It is the default generator for public ids (address-book guids, audit guids).

func OSFamily

func OSFamily(os string) string

OSFamily classifies a sysinfo "os" string (same rules as the SQL filter).

func ParseLegacyGUID

func ParseLegacyGUID(guid string) (groupID, userID, collectionID int64, ok bool)

ParseLegacyGUID splits a lejianwen guid "<group_id>-<user_id>-<collection_id>".

func RetentionCategories

func RetentionCategories() []string

RetentionCategories lists the categories in a stable order.

func RetentionSettingKey

func RetentionSettingKey(category string) string

RetentionSettingKey is the settings key of a retention category (PanelSettings.retention.<category>_days).

func ValidUsername added in v0.11.0

func ValidUsername(name string) bool

ValidUsername reports whether name is acceptable as a new username: 1-128 characters, letters, digits, '.', '_', '@' or '-'. Accounts created by the panel (admin API, LDAP) are held to it.

Types

type ABEntry

type ABEntry struct {
	ID               int64
	AddressBookID    int64
	RustdeskID       string
	Alias            string
	OSUsername       string
	Hostname         string
	Platform         string
	LoginName        string
	Note             string
	Password         string
	Hash             string
	ForceAlwaysRelay bool
	RDPPort          string
	RDPUsername      string
	SameServer       bool
	Tags             []string
	CreatedAt        time.Time
	UpdatedAt        time.Time

	// DeviceGroupName is joined from devices (same RustDesk ID), "" if unknown.
	DeviceGroupName string
	// DeviceID is the devices row with the same RustDesk ID (nil if unknown).
	DeviceID *int64
}

ABEntry is an address-book entry with its decrypted secrets and tag names.

type ABEntryPatch

type ABEntryPatch struct {
	Alias            *string
	OSUsername       *string
	Hostname         *string
	Platform         *string
	LoginName        *string
	Note             *string
	Password         *string
	Hash             *string
	ForceAlwaysRelay *bool
	RDPPort          *string
	RDPUsername      *string
	SameServer       *bool
	Tags             *[]string
}

ABEntryPatch is a partial entry update; nil fields are left unchanged. Password/Hash "" clears the secret. Tags replaces the tag set (missing tags are created with DefaultTagColor).

type ABPermission

type ABPermission int

ABPermission is the effective permission of a user on an address book. Values match the client's "rule" (1 read, 2 read/write, 3 full control).

const (
	ABNone      ABPermission = 0
	ABRead      ABPermission = 1
	ABReadWrite ABPermission = 2
	ABFull      ABPermission = 3
)

Address-book permissions.

func ParseABPermission

func ParseABPermission(s string) ABPermission

ParseABPermission maps the address_book_shares.permission column.

func (ABPermission) String

func (p ABPermission) String() string

String returns the address_book_shares.permission column value.

type ABShare

type ABShare struct {
	ID             int64
	AddressBookID  int64
	GranteeUserID  *int64
	GranteeGroupID *int64
	GranteeName    string
	Permission     ABPermission
	CreatedAt      time.Time
	UpdatedAt      time.Time
}

ABShare is a row of address_book_shares with the grantee's name joined in (username for users, group name for groups).

type ABTag

type ABTag struct {
	ID            int64
	AddressBookID int64
	Name          string
	Color         uint32
}

ABTag is a row of address_book_tags.

type ABTagInfo

type ABTagInfo struct {
	ABTag
	EntryCount int
}

ABTagInfo is a tag with the number of entries carrying it.

type ACLAction added in v0.7.0

type ACLAction string

ACLAction represents permission decision.

const (
	ACLActionAllow ACLAction = "allow"
	ACLActionDeny  ACLAction = "deny"
)

type ACLDecision added in v0.7.0

type ACLDecision string

ACLDecision represents the evaluated outcome.

const (
	ACLDecisionAllow   ACLDecision = "allow"
	ACLDecisionDeny    ACLDecision = "deny"
	ACLDecisionOwner   ACLDecision = "owner"
	ACLDecisionNoRules ACLDecision = "no_rules"
)

type ACLSubject added in v0.11.0

type ACLSubject struct {
	UserID        int64
	UserGroupID   *int64
	DeviceID      int64
	DeviceGroupID *int64
	// OwnerAccess: the user owns the device, or the device's owner is a
	// member of the user's "shared" user group. Such access is allowed unless
	// a rule denies it.
	OwnerAccess bool
}

ACLSubject is one (user, device) pair for DecideACL.

type APIToken added in v0.4.0

type APIToken struct {
	ID          int64
	UserID      int64
	Name        string
	Prefix      string
	TokenSHA256 []byte
	Scope       APITokenScope
	ExpiresAt   *time.Time
	CreatedAt   time.Time
	LastUsedAt  *time.Time
	LastUsedIP  string
	RevokedAt   *time.Time
}

APIToken is a row of api_tokens (a personal token for the admin API). The plain token is never stored, only its sha256.

func (*APIToken) Expired added in v0.4.0

func (t *APIToken) Expired(now time.Time) bool

Expired reports whether t has an expiry at or before now.

type APITokenScope added in v0.4.0

type APITokenScope string

APITokenScope limits what a personal API token may do.

const (
	// APITokenRead allows only safe methods (GET, HEAD).
	APITokenRead APITokenScope = "read"
	// APITokenWrite has the full rights of the owning user.
	APITokenWrite APITokenScope = "write"
)

API token scopes.

type APITokens added in v0.4.0

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

APITokens is the api_tokens repository.

func (*APITokens) CountForUser added in v0.4.0

func (r *APITokens) CountForUser(ctx context.Context, userID int64) (int, error)

CountForUser counts the non-revoked tokens of a user.

func (*APITokens) Create added in v0.4.0

func (r *APITokens) Create(ctx context.Context, t *APIToken) error

Create inserts t; ID and CreatedAt are set.

func (*APITokens) Get added in v0.4.0

func (r *APITokens) Get(ctx context.Context, id int64) (*APIToken, error)

Get returns a token by id regardless of state.

func (*APITokens) GetActive added in v0.4.0

func (r *APITokens) GetActive(ctx context.Context, hash []byte) (*APIToken, error)

GetActive returns the non-revoked, non-expired token with digest hash; anything else yields ErrNotFound.

func (*APITokens) ListForUser added in v0.4.0

func (r *APITokens) ListForUser(ctx context.Context, userID int64) ([]*APIToken, error)

ListForUser returns the non-revoked tokens of a user (expired ones included), newest first.

func (*APITokens) Revoke added in v0.4.0

func (r *APITokens) Revoke(ctx context.Context, id int64) error

Revoke marks a token revoked (idempotent); unknown ids return ErrNotFound.

func (*APITokens) Touch added in v0.4.0

func (r *APITokens) Touch(ctx context.Context, id int64, ip string) error

Touch records a use of the token from ip.

type AddressBook

type AddressBook struct {
	ID          int64
	GUID        string
	OwnerUserID int64
	Name        string
	Note        string
	IsPersonal  bool
	// LegacyCollectionID is the lejianwen collection id (0 = personal).
	LegacyCollectionID *int64
	LegacyGUID         string
	// DefaultPassword is the decrypted shared-book default password ("" = none).
	DefaultPassword string
	CreatedAt       time.Time
	UpdatedAt       time.Time

	OwnerUsername string
}

AddressBook is a row of address_books (owner username joined in).

type AddressBooks

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

AddressBooks is the repository for address_books and their entries, tags and (read side) shares. Secrets are sealed with associated data "ab_entry.password:<id>", "ab_entry.hash:<id>" and "address_book.password:<id>".

func (*AddressBooks) AddShare

func (r *AddressBooks) AddShare(ctx context.Context, bookID int64, userID, groupID *int64, perm ABPermission) error

AddShare grants a user (userID) or a user group (groupID) perm on a book, replacing an existing grant for the same grantee.

func (*AddressBooks) BooksContaining

func (r *AddressBooks) BooksContaining(ctx context.Context, rustdeskID string, visibleTo *int64) ([]BookRef, error)

BooksContaining returns the books with an entry for rustdeskID, ordered by name. With visibleTo set only books visible to that user are returned.

func (*AddressBooks) BulkEntries

func (r *AddressBooks) BulkEntries(ctx context.Context, bookID int64, ids []int64, action string, tags []string) (int, error)

BulkEntries applies action to the given entries of a book and returns how many entries were affected (ids not in the book are ignored). Added tag names are created with DefaultTagColor.

func (*AddressBooks) CountEntries

func (r *AddressBooks) CountEntries(ctx context.Context, bookID int64) (int, error)

CountEntries returns the number of entries in a book.

func (*AddressBooks) CountOwned

func (r *AddressBooks) CountOwned(ctx context.Context, userID int64) (int, error)

CountOwned counts the books owned by userID.

func (*AddressBooks) CountVisible

func (r *AddressBooks) CountVisible(ctx context.Context, visibleTo *int64) (int, error)

CountVisible counts books (all when visibleTo is nil, else those visible to the user).

func (*AddressBooks) Create

func (r *AddressBooks) Create(ctx context.Context, b *AddressBook) error

Create inserts b (a preset ID is honoured for legacy import). An empty GUID is generated. ID, GUID and timestamps are set.

func (*AddressBooks) CreateEntry

func (r *AddressBooks) CreateEntry(ctx context.Context, bookID int64, rustdeskID string, p ABEntryPatch) (int64, error)

CreateEntry adds rustdeskID to a book (ErrConflict when present) and applies p.

func (*AddressBooks) CreateShare

func (r *AddressBooks) CreateShare(ctx context.Context, bookID int64, userID, groupID *int64, perm ABPermission) (*ABShare, error)

CreateShare grants exactly one grantee perm on a book. ErrConflict when the grantee already has a share, ErrReferenced when the grantee does not exist.

func (*AddressBooks) CreateShared

func (r *AddressBooks) CreateShared(ctx context.Context, b *AddressBook) error

CreateShared creates a non-personal book (unique name, see ensureSharedNameFree).

func (*AddressBooks) CreateTag

func (r *AddressBooks) CreateTag(ctx context.Context, bookID int64, name string, color uint32) (int64, error)

CreateTag adds a tag (ErrConflict when the name exists) and returns its id.

func (*AddressBooks) DeleteBook

func (r *AddressBooks) DeleteBook(ctx context.Context, id int64) error

DeleteBook deletes book id (entries, tags and shares cascade).

func (*AddressBooks) DeleteEntries

func (r *AddressBooks) DeleteEntries(ctx context.Context, bookID int64, rustdeskIDs []string) (int64, error)

DeleteEntries removes the entries with the given RustDesk IDs and returns how many were deleted.

func (*AddressBooks) DeleteShare

func (r *AddressBooks) DeleteShare(ctx context.Context, bookID, id int64) error

DeleteShare removes share id.

func (*AddressBooks) DeleteTagByID

func (r *AddressBooks) DeleteTagByID(ctx context.Context, bookID, id int64) error

DeleteTagByID deletes tag id (removed from every entry).

func (*AddressBooks) DeleteTags

func (r *AddressBooks) DeleteTags(ctx context.Context, bookID int64, names []string) (int64, error)

DeleteTags removes tags by name (entries lose them via cascade) and returns how many were deleted.

func (*AddressBooks) EnsurePersonal

func (r *AddressBooks) EnsurePersonal(ctx context.Context, userID int64) (*AddressBook, error)

EnsurePersonal returns the personal book of userID, creating it if needed.

func (*AddressBooks) FindSharedByName

func (r *AddressBooks) FindSharedByName(ctx context.Context, name string) ([]*AddressBook, error)

FindSharedByName returns the non-personal books named name (case-insensitive).

func (*AddressBooks) Get

func (r *AddressBooks) Get(ctx context.Context, id int64) (*AddressBook, error)

Get returns the book with id.

func (*AddressBooks) GetByGUID

func (r *AddressBooks) GetByGUID(ctx context.Context, guid string) (*AddressBook, error)

GetByGUID resolves a client-supplied guid: the stable guid, a stored legacy guid, or (fallback) a legacy "<group_id>-<user_id>-<collection_id>" guid derived from the owner and legacy collection id. The group id part is ignored so moving a user between groups does not break cached guids.

func (*AddressBooks) GetEntry

func (r *AddressBooks) GetEntry(ctx context.Context, bookID int64, rustdeskID string) (*ABEntry, error)

GetEntry returns the entry for rustdeskID in a book (with tags).

func (*AddressBooks) GetEntryByID

func (r *AddressBooks) GetEntryByID(ctx context.Context, bookID, id int64) (*ABEntry, error)

GetEntryByID returns entry id of a book (with tags).

func (*AddressBooks) GetPersonal

func (r *AddressBooks) GetPersonal(ctx context.Context, userID int64) (*AddressBook, error)

GetPersonal returns the personal book of userID.

func (*AddressBooks) GetShare

func (r *AddressBooks) GetShare(ctx context.Context, bookID, id int64) (*ABShare, error)

GetShare returns share id of a book.

func (*AddressBooks) GetTagInfo

func (r *AddressBooks) GetTagInfo(ctx context.Context, bookID, id int64) (*ABTagInfo, error)

GetTagInfo returns tag id of a book.

func (*AddressBooks) ListBooks

func (r *AddressBooks) ListBooks(ctx context.Context, f BookListFilter) ([]BookListItem, int, error)

ListBooks returns a page of books matching f and the total count.

func (*AddressBooks) ListEntries

func (r *AddressBooks) ListEntries(ctx context.Context, bookID int64, limit, offset int) ([]*ABEntry, int, error)

ListEntries returns a page of a book's entries (ordered by id, tags sorted by name) and the total count. limit <= 0 returns every entry.

func (*AddressBooks) ListEntriesFiltered

func (r *AddressBooks) ListEntriesFiltered(ctx context.Context, bookID int64, f EntryListFilter) ([]*ABEntry, int, error)

ListEntriesFiltered returns a page of a book's entries (with tags) and the total.

func (*AddressBooks) ListShared

func (r *AddressBooks) ListShared(ctx context.Context, userID int64, limit, offset int) ([]SharedBook, int, error)

ListShared returns the non-personal books userID owns or that are shared with the user or the user's group, ordered by name, and the total count.

func (*AddressBooks) ListShares

func (r *AddressBooks) ListShares(ctx context.Context, bookID int64) ([]*ABShare, error)

ListShares returns the shares of a book (users first, then groups, by name).

func (*AddressBooks) ListTagInfos

func (r *AddressBooks) ListTagInfos(ctx context.Context, bookID int64) ([]*ABTagInfo, error)

ListTagInfos returns a book's tags ordered by name, with entry counts.

func (*AddressBooks) ListTags

func (r *AddressBooks) ListTags(ctx context.Context, bookID int64) ([]*ABTag, error)

ListTags returns a book's tags ordered by id (creation order).

func (*AddressBooks) PatchEntry

func (r *AddressBooks) PatchEntry(ctx context.Context, bookID int64, rustdeskID string, p ABEntryPatch) error

PatchEntry applies p to the existing entry for rustdeskID (ErrNotFound if absent).

func (*AddressBooks) PatchEntryByID

func (r *AddressBooks) PatchEntryByID(ctx context.Context, bookID, id int64, rustdeskID *string, p ABEntryPatch) error

PatchEntryByID applies p (and an optional new RustDesk id) to entry id.

func (*AddressBooks) Permission

func (r *AddressBooks) Permission(ctx context.Context, book *AddressBook, userID int64) (ABPermission, error)

Permission returns the effective permission of userID on book: the owner has full control; otherwise the maximum of the user's own grant and the grant to the user's group.

func (*AddressBooks) RenameTag

func (r *AddressBooks) RenameTag(ctx context.Context, bookID int64, old, newName string) error

RenameTag renames a tag; entries reference tags by id, so their tag lists follow. ErrNotFound when old is absent, ErrConflict when newName exists.

func (*AddressBooks) ReplaceAll

func (r *AddressBooks) ReplaceAll(ctx context.Context, bookID int64, entries []LegacyEntry, tags []string, colors map[string]uint32) error

ReplaceAll makes a book match a legacy full-replace push (POST /api/ab): listed entries are created or patched (absent keys keep their values), unlisted entries are deleted, and the tag set becomes tags plus every tag an entry references, with colours from colors (existing colour or DefaultTagColor when missing).

func (*AddressBooks) SetTagColor

func (r *AddressBooks) SetTagColor(ctx context.Context, bookID int64, name string, color uint32) error

SetTagColor changes the colour of an existing tag (ErrNotFound if absent).

func (*AddressBooks) UpdateBook

func (r *AddressBooks) UpdateBook(ctx context.Context, id int64, p BookPatch) error

UpdateBook applies p to book id.

func (*AddressBooks) UpdateShare

func (r *AddressBooks) UpdateShare(ctx context.Context, bookID, id int64, perm ABPermission) error

UpdateShare changes the permission of share id.

func (*AddressBooks) UpdateTagByID

func (r *AddressBooks) UpdateTagByID(ctx context.Context, bookID, id int64, name *string, color *uint32) error

UpdateTagByID renames and/or recolours tag id (entries keep the link).

func (*AddressBooks) UpsertEntry

func (r *AddressBooks) UpsertEntry(ctx context.Context, bookID int64, rustdeskID string, p ABEntryPatch) (bool, error)

UpsertEntry creates the entry for rustdeskID (or updates it when it already exists) and applies p. It reports whether a new entry was created.

func (*AddressBooks) UpsertTag

func (r *AddressBooks) UpsertTag(ctx context.Context, bookID int64, name string, color uint32) error

UpsertTag creates tag name with color, or updates the colour of an existing tag.

type AdminAudit

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

AdminAudit is the admin_audit repository.

func (*AdminAudit) List

func (r *AdminAudit) List(ctx context.Context, f AuditFilter) ([]*AuditEntry, error)

List returns entries matching f.

func (*AdminAudit) ListPanel

func (r *AdminAudit) ListPanel(ctx context.Context, f AdminAuditQuery) ([]*AuditEntry, int, error)

ListPanel returns a page of admin audit entries and the total.

func (*AdminAudit) PurgeBefore

func (r *AdminAudit) PurgeBefore(ctx context.Context, cutoff time.Time) (int64, error)

PurgeBefore deletes entries older than cutoff (retention).

func (*AdminAudit) Record

func (r *AdminAudit) Record(ctx context.Context, e *AuditEntry) error

Record appends e; ID and CreatedAt are set.

type AdminAuditQuery

type AdminAuditQuery struct {
	AuditQuery
	ActorUserID *int64
	// ActionPrefix matches e.g. "user." ; Action matches exactly.
	ActionPrefix string
	Action       string
	TargetType   string
}

AdminAuditQuery filters ListPanel.

type AlarmAudit

type AlarmAudit struct {
	ID           int64
	DeviceID     string
	DeviceUUID   string
	AlarmType    int
	ConnID       *int64
	ConnAuditRef string
	Info         string
	CreatedAt    time.Time
}

AlarmAudit is a row of alarm_audits (POST /api/audit/alarm).

type AlarmAuditQuery

type AlarmAuditQuery struct {
	AuditQuery
	AlarmType *int
}

AlarmAuditQuery filters ListPanel.

type AlarmAuditRow

type AlarmAuditRow struct {
	*AlarmAudit
	Device DeviceRef
}

AlarmAuditRow is an alarm audit with its device.

type AlarmAudits

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

AlarmAudits is the alarm_audits repository.

func (*AlarmAudits) Create

func (r *AlarmAudits) Create(ctx context.Context, a *AlarmAudit) error

Create inserts a.

func (*AlarmAudits) List

List returns alarm audits matching f.

func (*AlarmAudits) ListPanel

func (r *AlarmAudits) ListPanel(ctx context.Context, f AlarmAuditQuery) ([]AlarmAuditRow, int, error)

ListPanel returns a page of alarm audits and the total.

type Asset

type Asset struct {
	Name        string
	ContentType string
	Data        []byte
	SHA256      []byte
	UpdatedAt   time.Time
}

Asset is a row of panel_assets.

type Assets

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

Assets is the panel_assets repository.

func (*Assets) Delete

func (r *Assets) Delete(ctx context.Context, name string) (bool, error)

Delete removes asset name; it reports whether it existed.

func (*Assets) Exists

func (r *Assets) Exists(ctx context.Context, name string) (bool, []byte, error)

Exists reports whether asset name is stored, with its digest.

func (*Assets) Get

func (r *Assets) Get(ctx context.Context, name string) (*Asset, error)

Get returns the asset name.

func (*Assets) Put

func (r *Assets) Put(ctx context.Context, a *Asset, updatedBy *int64) error

Put stores (replaces) asset a; SHA256 and UpdatedAt are set.

type AuditEntry

type AuditEntry struct {
	ID          int64
	ActorUserID *int64
	// ActorName is a snapshot ("cli" for command-line actions).
	ActorName  string
	ActorIP    string
	Action     string
	TargetType string
	TargetID   string
	// Details must never contain secrets.
	Details   map[string]any
	CreatedAt time.Time
}

AuditEntry is a row of admin_audit.

type AuditFilter

type AuditFilter struct {
	ActorUserID *int64
	// ActionPrefix matches e.g. "user." for all user actions.
	ActionPrefix string
	TargetType   string
	TargetID     string
	Since        *time.Time
	Until        *time.Time
	BeforeID     int64
	Limit        int
}

AuditFilter selects audit entries. Results are newest first; page with BeforeID (keyset pagination: pass the last ID of the previous page).

type AuditNonces

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

AuditNonces de-duplicates client audit retries (clients >= 1.5.0).

func (*AuditNonces) Claim

func (r *AuditNonces) Claim(ctx context.Context, nonce string) (bool, error)

Claim records nonce and reports true, or reports false when it was already seen (a retry of a stored record). Run it in the same transaction as the audit insert so a failed write releases the nonce.

func (*AuditNonces) PurgeBefore

func (r *AuditNonces) PurgeBefore(ctx context.Context, cutoff time.Time) (int64, error)

PurgeBefore deletes nonces recorded before cutoff.

type AuditQuery

type AuditQuery struct {
	// Q is a case-insensitive substring search over the category's text columns.
	Q     string
	Since *time.Time // inclusive
	Until *time.Time // exclusive
	// Desc orders newest first.
	Desc   bool
	Limit  int
	Offset int
}

AuditQuery holds the filters shared by every panel audit list.

type AuthToken

type AuthToken struct {
	ID          int64
	UserID      int64
	Kind        TokenKind
	TokenSHA256 []byte
	// JWTExpiresAt is the fixed JWT exp (client tokens only).
	JWTExpiresAt *time.Time
	// ExpiresAt is the sliding (client) or idle (web) expiry.
	ExpiresAt time.Time
	// AbsoluteExpiresAt caps web sessions regardless of activity.
	AbsoluteExpiresAt *time.Time
	DeviceRustdeskID  string
	DeviceUUID        string
	ClientPlatform    string
	UserAgent         string
	IP                string
	MFAPending        bool
	CreatedAt         time.Time
	LastUsedAt        *time.Time
	RevokedAt         *time.Time
	RevokeReason      string
	LegacyID          *int64
}

AuthToken is a row of auth_tokens. The plain token is never stored.

type AuthTokens

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

AuthTokens is the auth_tokens repository.

func (*AuthTokens) Create

func (r *AuthTokens) Create(ctx context.Context, t *AuthToken) error

Create inserts t; ID and CreatedAt are set.

func (*AuthTokens) Get

func (r *AuthTokens) Get(ctx context.Context, id int64) (*AuthToken, error)

Get returns a token by id regardless of state.

func (*AuthTokens) GetActive

func (r *AuthTokens) GetActive(ctx context.Context, kind TokenKind, hash []byte) (*AuthToken, error)

GetActive returns the non-revoked, non-expired token of the given kind with digest hash. Expired, revoked or unknown tokens yield ErrNotFound.

func (*AuthTokens) Inactive added in v0.12.0

func (r *AuthTokens) Inactive(ctx context.Context, kind TokenKind, hash []byte) (bool, error)

Inactive reports whether a token of the given kind with digest hash is recorded but no longer active (revoked, or past its sliding, absolute or JWT expiry). Digests without a row (e.g. the short-lived tokens handed to the web client) are not inactive.

func (*AuthTokens) ListActiveForUser

func (r *AuthTokens) ListActiveForUser(ctx context.Context, userID int64, kind TokenKind) ([]*AuthToken, error)

ListActiveForUser returns a user's active tokens, newest first (kind "" = all).

func (*AuthTokens) PurgeInactive

func (r *AuthTokens) PurgeInactive(ctx context.Context, cutoff time.Time) (int64, error)

PurgeInactive deletes tokens that expired or were revoked before cutoff and returns the number deleted (janitor).

func (*AuthTokens) Revoke

func (r *AuthTokens) Revoke(ctx context.Context, id int64, reason string) error

Revoke marks one token revoked. Revoking an already revoked token is a no-op that still returns nil; unknown ids return ErrNotFound.

func (*AuthTokens) RevokeForDevice

func (r *AuthTokens) RevokeForDevice(ctx context.Context, deviceUUID string, reason string) (int64, error)

RevokeForDevice revokes all active client tokens bound to a device uuid (device deletion in the panel).

func (*AuthTokens) RevokeForUser

func (r *AuthTokens) RevokeForUser(ctx context.Context, userID int64, kind TokenKind, reason string) (int64, error)

RevokeForUser revokes all active tokens of a user (of kind, or all kinds when kind is "") and returns how many were revoked.

func (*AuthTokens) SetMFAPending

func (r *AuthTokens) SetMFAPending(ctx context.Context, id int64, pending bool) error

SetMFAPending flips the pending-second-factor flag of a web session.

func (*AuthTokens) Touch

func (r *AuthTokens) Touch(ctx context.Context, id int64, newExpiry *time.Time) error

Touch records use of a token and, when newExpiry is non-nil, slides its expiry (never beyond absolute_expires_at for web sessions).

type BookListFilter

type BookListFilter struct {
	// ViewerID computes Rule (and, unless All, restricts to books with a rule > 0).
	ViewerID int64
	// All lists every book regardless of the viewer's rule (admin scope=all).
	All bool
	// ID restricts to one book.
	ID          int64
	OwnerUserID *int64
	// Kind is "personal", "shared" or "" (both).
	Kind string
	// Q matches name, note or owner username (case-insensitive substring).
	Q string
	// Sort: name, entry_count or updated_at, "-" prefix for descending.
	Sort   string
	Limit  int
	Offset int
}

BookListFilter selects address books for the panel.

type BookListItem

type BookListItem struct {
	*AddressBook
	OwnerDisplayName string
	Rule             ABPermission
	EntryCount       int
	ShareCount       int
}

BookListItem is a book with the viewer's rule and counters.

type BookPatch

type BookPatch struct {
	Name            *string
	Note            *string
	DefaultPassword *string
}

BookPatch is a partial book update; nil fields are kept. DefaultPassword "" clears the password.

type BookRef

type BookRef struct {
	ID            int64
	Name          string
	IsPersonal    bool
	OwnerUsername string
}

BookRef identifies a book containing a device.

type ClientAuditFilter

type ClientAuditFilter struct {
	DeviceID string
	Since    *time.Time
	Until    *time.Time
	BeforeID int64
	Limit    int
}

ClientAuditFilter selects client audit rows (newest first, keyset paging).

type ClientStrategies added in v0.7.0

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

ClientStrategies is the repository for client MDM strategies.

func (*ClientStrategies) Create added in v0.7.0

Create inserts s. If s.IsDefault is true, all other strategies are marked non-default.

func (*ClientStrategies) Delete added in v0.7.0

func (r *ClientStrategies) Delete(ctx context.Context, id int64) error

Delete removes strategy id. It returns ErrInvalid if the strategy is the default.

func (*ClientStrategies) Get added in v0.7.0

Get returns the strategy with the given ID.

func (*ClientStrategies) GetByName added in v0.7.0

func (r *ClientStrategies) GetByName(ctx context.Context, name string) (*ClientStrategy, error)

GetByName returns the strategy with the given name (case-insensitive).

func (*ClientStrategies) GetDefault added in v0.7.0

func (r *ClientStrategies) GetDefault(ctx context.Context) (*ClientStrategy, error)

GetDefault returns the default strategy (is_default = 1), or ErrNotFound.

func (*ClientStrategies) List added in v0.7.0

List returns all strategies ordered by is_default DESC, name COLLATE NOCASE.

func (*ClientStrategies) ManagedKeys added in v0.11.0

func (r *ClientStrategies) ManagedKeys(ctx context.Context) (map[string]struct{}, error)

ManagedKeys returns every option name that some strategy sets: on a device under a strategy the panel owns all of them.

func (*ClientStrategies) ResolveForDevice added in v0.7.0

func (r *ClientStrategies) ResolveForDevice(ctx context.Context, d *Device) (*ClientStrategy, error)

ResolveForDevice resolves the effective MDM strategy for a device, or nil: 1. Device's own strategy_id (if set) 2. Device group's strategy_id (if device belongs to a group with strategy_id set) 3. System default strategy (is_default = 1), when there is one

It runs on every heartbeat, so it reads no device counts.

func (*ClientStrategies) SetDefault added in v0.7.0

func (r *ClientStrategies) SetDefault(ctx context.Context, id int64) error

SetDefault marks strategy id as the default, unsetting all others. An unknown id is ErrNotFound and changes nothing.

func (*ClientStrategies) Update added in v0.7.0

Update updates name, note, config_options, is_default for s.

type ClientStrategy added in v0.7.0

type ClientStrategy struct {
	ID            int64             `json:"id"`
	Name          string            `json:"name"`
	Note          string            `json:"note"`
	ConfigOptions map[string]string `json:"config_options"`
	IsDefault     bool              `json:"is_default"`
	DeviceCount   int               `json:"device_count"`
	CreatedAt     time.Time         `json:"created_at"`
	UpdatedAt     time.Time         `json:"updated_at"`
}

ClientStrategy is an MDM configuration policy applied to RustDesk clients.

type ConnAuditQuery

type ConnAuditQuery struct {
	AuditQuery
	Scope    DeviceAuditScope
	ConnType *int
	// Active: true = without ended_at, false = ended.
	Active *bool
	// SortEnded orders by ended_at instead of started_at.
	SortEnded bool
}

ConnAuditQuery filters ListPanel.

type ConnAuditRow

type ConnAuditRow struct {
	*ConnectionAudit
	Device DeviceRef
}

ConnAuditRow is a connection audit with its device.

type ConnectionACL added in v0.7.0

type ConnectionACL struct {
	ID            int64  `json:"id"`
	Name          string `json:"name"`
	Note          string `json:"note"`
	UserID        *int64 `json:"user_id"`
	UserName      string `json:"user_name,omitempty"`
	UserGroupID   *int64 `json:"user_group_id"`
	UserGroupName string `json:"user_group_name,omitempty"`
	DeviceID      *int64 `json:"device_id"`
	DeviceName    string `json:"device_name,omitempty"`
	// DeviceRustdeskID is the RustDesk id of DeviceID (what policy selectors use).
	DeviceRustdeskID string    `json:"device_rustdesk_id,omitempty"`
	DeviceGroupID    *int64    `json:"device_group_id"`
	DeviceGroupName  string    `json:"device_group_name,omitempty"`
	ControlRoleID    *int64    `json:"control_role_id"`
	ControlRoleName  string    `json:"control_role_name,omitempty"`
	Action           ACLAction `json:"action"`
	Priority         int       `json:"priority"`
	Enabled          bool      `json:"enabled"`
	CreatedAt        time.Time `json:"created_at"`
	UpdatedAt        time.Time `json:"updated_at"`
}

ConnectionACL is a rule in the access matrix.

type ConnectionACLs added in v0.7.0

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

ConnectionACLs repository.

func (*ConnectionACLs) Create added in v0.7.0

func (r *ConnectionACLs) Create(ctx context.Context, a *ConnectionACL) error

Create inserts a new ACL rule.

func (*ConnectionACLs) Delete added in v0.7.0

func (r *ConnectionACLs) Delete(ctx context.Context, id int64) error

Delete removes rule id.

func (*ConnectionACLs) EffectiveRole added in v0.12.0

func (r *ConnectionACLs) EffectiveRole(ctx context.Context, rule *ConnectionACL) (*ControlRole, error)

EffectiveRole is the control role of a connection allowed by rule (nil: allowed without a matching rule): the rule's role, else the default role. It is nil only when no role exists at all.

func (*ConnectionACLs) Evaluate added in v0.7.0

func (r *ConnectionACLs) Evaluate(
	ctx context.Context,
	userID int64,
	deviceID int64,
) (ACLDecision, *ConnectionACL, *ControlRole, error)

Evaluate checks connection permission between userID and deviceID and returns the effective control role of allowed connections (the rule's role, else the default role).

func (*ConnectionACLs) EvaluateDevice added in v0.12.0

func (r *ConnectionACLs) EvaluateDevice(
	ctx context.Context,
	userID int64,
	d *Device,
) (ACLDecision, *ConnectionACL, *ControlRole, error)

EvaluateDevice is Evaluate for an already loaded device (its ID, OwnerUserID and DeviceGroupID are used), saving the device lookup.

func (*ConnectionACLs) FilterAccessibleDevices added in v0.7.0

func (r *ConnectionACLs) FilterAccessibleDevices(ctx context.Context, userID int64, devices []*Device) ([]*Device, error)

FilterAccessibleDevices filters devices to only those permitted for userID (the rules are loaded once).

func (*ConnectionACLs) ForUser added in v0.11.0

func (r *ConnectionACLs) ForUser(ctx context.Context, userID int64) (*UserACL, error)

ForUser loads what deciding userID's connections needs: the user's group, the members of that group when it is "shared", and all rules.

func (*ConnectionACLs) Get added in v0.7.0

func (r *ConnectionACLs) Get(ctx context.Context, id int64) (*ConnectionACL, error)

Get finds a rule by ID.

func (*ConnectionACLs) HasEnabledRules added in v0.11.0

func (r *ConnectionACLs) HasEnabledRules(ctx context.Context) (bool, error)

HasEnabledRules reports whether any connection rule is enabled (without one, every connection is allowed).

func (*ConnectionACLs) List added in v0.7.0

func (r *ConnectionACLs) List(ctx context.Context) ([]*ConnectionACL, error)

List returns all rules ordered by priority ASC, id ASC.

func (*ConnectionACLs) Update added in v0.7.0

func (r *ConnectionACLs) Update(ctx context.Context, a *ConnectionACL) error

Update modifies an existing ACL rule.

type ConnectionAudit

type ConnectionAudit struct {
	ID         int64
	GUID       string
	DeviceID   string // controlled device RustDesk ID
	DeviceUUID string
	ConnID     int64
	// SessionID is the client's u64 session id in decimal ("" = unknown).
	SessionID            string
	ConnType             int
	PrimaryAuth          *int
	TwoFactor            *int
	ConnAuditRef         string
	ControllerRustdeskID string
	ControllerName       string
	ControllerIP         string
	Note                 string
	StartedAt            time.Time
	EndedAt              *time.Time
	CreatedAt            time.Time
	UpdatedAt            time.Time
}

ConnectionAudit is a row of connection_audits (POST /api/audit/conn).

type ConnectionAudits

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

ConnectionAudits is the connection_audits repository.

func (*ConnectionAudits) ConnectionStats

func (r *ConnectionAudits) ConnectionStats(ctx context.Context, since time.Time, ownerID *int64) (total, active int, hourly map[int64]int, err error)

ConnectionStats counts connections started since `since` (optionally only to devices owned by ownerID): total, still open, and per hour.

func (*ConnectionAudits) Create

Create inserts a; an empty GUID is generated, a zero StartedAt is now.

func (*ConnectionAudits) FindBySession

func (r *ConnectionAudits) FindBySession(ctx context.Context, deviceID, sessionID string, connType *int) (*ConnectionAudit, error)

FindBySession returns the newest record of (device, sessionID), optionally restricted to connType.

func (*ConnectionAudits) FindOpen

func (r *ConnectionAudits) FindOpen(ctx context.Context, deviceID string, connID int64, maxAge time.Duration) (*ConnectionAudit, error)

FindOpen returns the newest record of (device, connID) that has not ended. conn_id is a client-local counter, so only open records started within maxAge are considered.

func (*ConnectionAudits) GetByGUID

func (r *ConnectionAudits) GetByGUID(ctx context.Context, guid string) (*ConnectionAudit, error)

GetByGUID returns the record with guid.

func (*ConnectionAudits) List

List returns connection audits matching f.

func (*ConnectionAudits) ListPanel

ListPanel returns a page of connection audits and the total.

func (*ConnectionAudits) SetNote

func (r *ConnectionAudits) SetNote(ctx context.Context, guid, note string) error

SetNote sets the note of the record with guid.

func (*ConnectionAudits) Update

Update writes every mutable column of a.

type ControlRole added in v0.7.0

type ControlRole struct {
	ID                 int64     `json:"id"`
	Name               string    `json:"name"`
	Note               string    `json:"note"`
	AllowKeyboardMouse bool      `json:"allow_keyboard_mouse"`
	AllowClipboard     bool      `json:"allow_clipboard"`
	AllowFileTransfer  bool      `json:"allow_file_transfer"`
	AllowAudio         bool      `json:"allow_audio"`
	AllowTCPTunneling  bool      `json:"allow_tcp_tunneling"`
	AllowTerminal      bool      `json:"allow_terminal"`
	AllowRestart       bool      `json:"allow_restart"`
	IsDefault          bool      `json:"is_default"`
	RuleCount          int       `json:"rule_count"`
	CreatedAt          time.Time `json:"created_at"`
	UpdatedAt          time.Time `json:"updated_at"`
}

ControlRole defines session capability permissions.

type ControlRoles added in v0.7.0

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

ControlRoles repository.

func (*ControlRoles) Create added in v0.7.0

func (r *ControlRoles) Create(ctx context.Context, cr *ControlRole) error

Create inserts a new control role.

func (*ControlRoles) Delete added in v0.7.0

func (r *ControlRoles) Delete(ctx context.Context, id int64) error

Delete removes role id. The default role (ErrInvalid) and a role that any rule references, enabled or not (ErrRoleInUse), cannot be deleted.

func (*ControlRoles) Get added in v0.7.0

func (r *ControlRoles) Get(ctx context.Context, id int64) (*ControlRole, error)

Get finds a role by ID.

func (*ControlRoles) GetByName added in v0.7.0

func (r *ControlRoles) GetByName(ctx context.Context, name string) (*ControlRole, error)

GetByName finds a role by Name.

func (*ControlRoles) GetDefault added in v0.7.0

func (r *ControlRoles) GetDefault(ctx context.Context) (*ControlRole, error)

GetDefault finds the default control role.

func (*ControlRoles) List added in v0.7.0

func (r *ControlRoles) List(ctx context.Context) ([]*ControlRole, error)

List returns all control roles.

func (*ControlRoles) SetDefault added in v0.7.0

func (r *ControlRoles) SetDefault(ctx context.Context, id int64) error

SetDefault marks role id as default. An unknown id is ErrNotFound and changes nothing.

func (*ControlRoles) Update added in v0.7.0

func (r *ControlRoles) Update(ctx context.Context, cr *ControlRole) error

Update modifies an existing role.

type Device

type Device struct {
	ID            int64
	RustdeskID    string
	UUID          string // "" = NULL (not yet reported)
	Hostname      string
	OS            string
	CPU           string
	Memory        string
	OSUsername    string
	ClientVersion string
	Alias         string
	Note          string
	OwnerUserID   *int64
	DeviceGroupID *int64
	StrategyID    *int64
	// PublicKey is the device's Ed25519 public key (32 bytes) when known.
	PublicKey          []byte
	LastSeenAt         *time.Time
	LastSeenIP         string
	LastHeartbeatAt    *time.Time
	SysinfoAt          *time.Time
	SysinfoRequestedAt *time.Time
	CreatedAt          time.Time
	UpdatedAt          time.Time

	// Read-only joins.
	OwnerUsername   string
	DeviceGroupName string
	StrategyName    string
}

Device is a row of devices (one per RustDesk ID), with the owner's username and the device group's name joined in for reads.

func (*Device) SysinfoPending

func (d *Device) SysinfoPending() bool

SysinfoPending reports whether the server asked for a sysinfo re-upload that has not arrived yet (or the device never uploaded sysinfo).

type DeviceAuditScope

type DeviceAuditScope struct {
	// OwnerUserID: only audits of devices owned by this user.
	OwnerUserID *int64
	// DeviceRowID: only audits of this device row.
	DeviceRowID *int64
}

DeviceAuditScope restricts device audits.

type DeviceGroup

type DeviceGroup struct {
	ID         int64
	Name       string
	Note       string
	StrategyID *int64
	CreatedAt  time.Time
	UpdatedAt  time.Time
}

DeviceGroup is a row of device_groups.

type DeviceGroupRow

type DeviceGroupRow struct {
	*DeviceGroup
	DeviceCount  int
	StrategyName string
}

DeviceGroupRow is a device group with its device count.

type DeviceGroups

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

DeviceGroups is the device_groups repository (read side plus Create).

func (*DeviceGroups) Create

func (r *DeviceGroups) Create(ctx context.Context, g *DeviceGroup) error

Create inserts g (honouring a preset ID for legacy import).

func (*DeviceGroups) Delete

func (r *DeviceGroups) Delete(ctx context.Context, id int64) error

Delete removes a device group; its devices' device_group_id becomes NULL.

func (*DeviceGroups) Get

func (r *DeviceGroups) Get(ctx context.Context, id int64) (*DeviceGroup, error)

Get returns the group with id.

func (*DeviceGroups) GetByName

func (r *DeviceGroups) GetByName(ctx context.Context, name string) (*DeviceGroup, error)

GetByName returns the group named name (case-insensitive).

func (*DeviceGroups) GetRow

func (r *DeviceGroups) GetRow(ctx context.Context, id int64) (*DeviceGroupRow, error)

GetRow returns one device group with its device count.

func (*DeviceGroups) List

func (r *DeviceGroups) List(ctx context.Context, scope DeviceScope, limit, offset int) ([]*DeviceGroup, int, error)

List returns a page of device groups visible within scope, ordered by name, and the total count. With a non-zero scope only groups containing at least one device in scope are returned.

func (*DeviceGroups) Search

func (r *DeviceGroups) Search(ctx context.Context, p GroupSearch) ([]*DeviceGroupRow, int, error)

Search returns a page of device groups with device counts.

func (*DeviceGroups) Update

func (r *DeviceGroups) Update(ctx context.Context, g *DeviceGroup) error

Update writes name, note and strategy_id.

type DeviceRef

type DeviceRef struct {
	ID    *int64
	Alias *string
}

DeviceRef is the device joined to an audit row (nil fields when unknown).

type DeviceScope

type DeviceScope struct {
	// OwnerUserID limits to devices owned by this user.
	OwnerUserID *int64
	// OwnerGroupID limits to devices owned by members of this user group.
	OwnerGroupID *int64
}

DeviceScope restricts device listings. The zero value matches every device.

type DeviceSearch

type DeviceSearch struct {
	// OwnerUserID limits to devices owned by this user; OwnerNone to unassigned devices.
	OwnerUserID *int64
	OwnerNone   bool
	// DeviceGroupID limits to one device group; GroupNone to devices without a group.
	DeviceGroupID *int64
	GroupNone     bool
	// StrategyID limits to one strategy; StrategyNone to devices without a direct strategy override.
	StrategyID   *int64
	StrategyNone bool
	// OSFamily is one of OSFamilies ("" = any).
	OSFamily string
	// Version is an exact client version ("" = any).
	Version   string
	SeenAfter *time.Time
	// Query matches RustDesk ID, hostname, alias, OS username or note (substring).
	Query string
	// Online filters by live presence (nil = any).
	Online *bool
	// OnlineIDs is the set of RustDesk IDs currently online (live presence).
	// When nil, a device counts as online when its last heartbeat is at or
	// after HeartbeatSince (fallback when presence is unavailable).
	OnlineIDs      []string
	HeartbeatSince time.Time
	// Sort is one of DeviceSortKeys ("" = last_seen_at); Desc reverses it.
	Sort   string
	Desc   bool
	Limit  int
	Offset int
}

DeviceSearch filters, sorts and pages Devices.Search.

type Devices

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

Devices is the devices repository.

func (*Devices) BindOwner

func (r *Devices) BindOwner(ctx context.Context, rustdeskID, uuid string, userID int64) (bool, error)

BindOwner sets the owner of the device with rustdeskID whose uuid matches (client login). A device without a stored uuid is not bound. It reports whether a device was bound.

func (*Devices) Count

func (r *Devices) Count(ctx context.Context, p DeviceSearch) (int, error)

Count returns the number of devices matching p.

func (*Devices) Create

func (r *Devices) Create(ctx context.Context, d *Device) error

Create inserts d; ID, CreatedAt and UpdatedAt are set.

func (*Devices) Delete

func (r *Devices) Delete(ctx context.Context, id int64) error

Delete removes a device.

func (*Devices) Facets

func (r *Devices) Facets(ctx context.Context, p DeviceSearch) (total int, oses, versions []Facet, err error)

Facets returns the OS families and client versions (non-empty) of the devices matching p, by count descending.

func (*Devices) Get

func (r *Devices) Get(ctx context.Context, id int64) (*Device, error)

Get returns the device with id.

func (*Devices) GetByRustdeskID

func (r *Devices) GetByRustdeskID(ctx context.Context, rustdeskID string) (*Device, error)

GetByRustdeskID returns the device with the given RustDesk ID.

func (*Devices) GuessOwner

func (r *Devices) GuessOwner(ctx context.Context, rustdeskID, uuid string) (int64, error)

GuessOwner returns the user of the newest active client token issued to the device (rustdeskID, uuid), used to bind a device created by its first sysinfo after the user already logged in. ErrNotFound when none.

func (*Devices) List

func (r *Devices) List(ctx context.Context, p ListDevicesParams) ([]*Device, int, error)

List returns a page of devices ordered by id and the total match count.

func (*Devices) RequestSysinfo

func (r *Devices) RequestSysinfo(ctx context.Context, id int64) error

RequestSysinfo asks the device to re-upload sysinfo on its next heartbeat.

func (*Devices) Search

func (r *Devices) Search(ctx context.Context, p DeviceSearch) ([]*Device, int, error)

Search returns a page of devices matching p and the total match count.

func (*Devices) SearchEach

func (r *Devices) SearchEach(ctx context.Context, p DeviceSearch, fn func(*Device) error) error

SearchEach calls fn for every device matching p (Limit/Offset ignored), in p's order, stopping at the first error.

func (*Devices) SetIdentity

func (r *Devices) SetIdentity(ctx context.Context, id int64, uuid string, pk []byte) error

SetIdentity sets the uuid and (when non-nil) the public key of a device.

func (*Devices) TouchHeartbeat

func (r *Devices) TouchHeartbeat(ctx context.Context, id int64, ip string, minInterval time.Duration) (bool, error)

TouchHeartbeat records a heartbeat from ip. To bound write volume (clients beat every 3 s while controlled) the row is only written when the previous heartbeat is older than minInterval or the IP changed. It reports whether a write happened.

func (*Devices) TouchSeen

func (r *Devices) TouchSeen(ctx context.Context, id int64, at time.Time) error

TouchSeen records a presence observation (hbbs online poll) without touching the heartbeat timestamp.

func (*Devices) UnbindOwner

func (r *Devices) UnbindOwner(ctx context.Context, rustdeskID, uuid string, userID int64) error

UnbindOwner clears the owner of the device with rustdeskID/uuid when it is userID (client logout).

func (*Devices) Update

func (r *Devices) Update(ctx context.Context, d *Device) error

Update writes the administrative fields of d: alias, note, owner, device group, hostname and OS username.

func (*Devices) UpdateSysinfo

func (r *Devices) UpdateSysinfo(ctx context.Context, id int64, s Sysinfo) error

UpdateSysinfo stores a sysinfo upload and marks sysinfo_at.

type EmailCode

type EmailCode struct {
	ID         int64
	UserID     int64
	Purpose    string
	Email      string
	CodeSHA256 []byte
	Attempts   int
	IP         string
	CreatedAt  time.Time
	ExpiresAt  time.Time
	ConsumedAt *time.Time
}

EmailCode is a row of email_codes: a one-time code or reset token sent by e-mail. Only its sha256 is stored.

type EmailCodes

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

EmailCodes is the email_codes repository.

func (*EmailCodes) Active

func (r *EmailCodes) Active(ctx context.Context, userID int64, purpose string) (*EmailCode, error)

Active returns the newest unconsumed, unexpired code of the user for purpose; ErrNotFound when none.

func (*EmailCodes) ActiveByHash

func (r *EmailCodes) ActiveByHash(ctx context.Context, purpose string, sum []byte) (*EmailCode, error)

ActiveByHash returns the unconsumed, unexpired code with digest sum for purpose (reset tokens); ErrNotFound when none.

func (*EmailCodes) Consume

func (r *EmailCodes) Consume(ctx context.Context, id int64) error

Consume marks code id used; ErrNotFound when it was already consumed (a concurrent use won).

func (*EmailCodes) ConsumeAll

func (r *EmailCodes) ConsumeAll(ctx context.Context, userID int64, purpose string) error

ConsumeAll invalidates every unconsumed code of the user for purpose.

func (*EmailCodes) CountForIPSince

func (r *EmailCodes) CountForIPSince(ctx context.Context, ip string, t time.Time) (int, error)

CountForIPSince counts codes requested from ip (any user) since t.

func (*EmailCodes) CountForUserSince

func (r *EmailCodes) CountForUserSince(ctx context.Context, userID int64, t time.Time) (int, error)

CountForUserSince counts codes sent to the user (any purpose) since t.

func (*EmailCodes) Create

func (r *EmailCodes) Create(ctx context.Context, c *EmailCode) error

Create invalidates the user's unconsumed codes of the same purpose and inserts c (ID and CreatedAt are set). Run it in a transaction.

func (*EmailCodes) Fail

func (r *EmailCodes) Fail(ctx context.Context, id int64, maxAttempts int) (int, error)

Fail records a wrong guess against code id and invalidates it once maxAttempts wrong guesses were made. It returns the remaining attempts.

func (*EmailCodes) Latest

func (r *EmailCodes) Latest(ctx context.Context, userID int64, purpose string) (*EmailCode, error)

Latest returns the newest code of the user for purpose in any state (resend cooldown); ErrNotFound when none.

func (*EmailCodes) PurgeBefore

func (r *EmailCodes) PurgeBefore(ctx context.Context, t time.Time) (int64, error)

PurgeBefore deletes codes that expired before t.

type EntryListFilter

type EntryListFilter struct {
	// Q matches rustdesk id, alias, hostname, os username, platform or note.
	Q string
	// Tags: only entries having every tag.
	Tags []string
	// Sort: alias, rustdesk_id, hostname or updated_at ("-" = descending).
	Sort   string
	Limit  int
	Offset int
}

EntryListFilter selects entries of a book.

type Facet

type Facet struct {
	Value string
	Count int
}

Facet is one value of a facet with its device count.

type FileAuditQuery

type FileAuditQuery struct {
	AuditQuery
	Scope     DeviceAuditScope
	Direction *int
}

FileAuditQuery filters ListPanel.

type FileAuditRow

type FileAuditRow struct {
	*FileTransferAudit
	Device DeviceRef
}

FileAuditRow is a file-transfer audit with its device.

type FileTransferAudit

type FileTransferAudit struct {
	ID                   int64
	DeviceID             string
	DeviceUUID           string
	ControllerRustdeskID string
	ControllerName       string
	ControllerIP         string
	// Direction: 0 controlled->controller, 1 controller->controlled.
	Direction int
	IsFile    bool
	Path      string
	FileCount int64
	// Info is the client JSON (must be valid JSON; "" stores "{}").
	Info      string
	CreatedAt time.Time
}

FileTransferAudit is a row of file_transfer_audits (POST /api/audit/file).

type FileTransferAudits

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

FileTransferAudits is the file_transfer_audits repository.

func (*FileTransferAudits) Create

Create inserts a.

func (*FileTransferAudits) List

List returns file transfer audits matching f.

func (*FileTransferAudits) ListPanel

ListPanel returns a page of file transfer audits and the total.

type GroupRef

type GroupRef struct {
	ID   int64
	Name string
}

GroupRef is a minimal group identity (id + name).

type GroupSearch

type GroupSearch struct {
	Query string
	// Sort: name, created_at, or count (member/device count).
	Sort   string
	Desc   bool
	Limit  int
	Offset int
}

GroupSearch filters, sorts and pages group listings.

type GroupVisibility

type GroupVisibility string

GroupVisibility controls what members of a user group see in the client.

const (
	// VisibilitySelf: members see only their own devices (legacy type 1).
	VisibilitySelf GroupVisibility = "self"
	// VisibilityShared: members see each other's devices and users (legacy type 2).
	VisibilityShared GroupVisibility = "shared"
)

Group visibilities.

type IdentityProvider

type IdentityProvider struct {
	ID                  int64
	Slug                string
	Kind                ProviderKind
	DisplayName         string
	ClientID            string
	ClientSecretEnc     []byte
	Issuer              string
	Scopes              []string
	PKCEEnabled         bool
	PKCEMethod          string
	AutoRegister        bool
	LinkByVerifiedEmail bool
	Enabled             bool
	SortOrder           int
	CreatedAt           time.Time
	UpdatedAt           time.Time
}

IdentityProvider is a row of identity_providers. ClientSecretEnc is the AEAD ciphertext (associated data crypto.IdentityProviderClientSecretAD); it is never returned by the API.

type IdentityProviders

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

IdentityProviders is the identity_providers repository.

func (*IdentityProviders) Create

Create inserts p (ID honoured when non-zero, for the legacy importer). ID, CreatedAt and UpdatedAt are set.

func (*IdentityProviders) Delete

func (r *IdentityProviders) Delete(ctx context.Context, id int64) error

Delete removes a provider (its identities and pending states cascade).

func (*IdentityProviders) Get

Get returns a provider by id.

func (*IdentityProviders) GetBySlug

func (r *IdentityProviders) GetBySlug(ctx context.Context, slug string) (*IdentityProvider, error)

GetBySlug returns a provider by slug (exact match).

func (*IdentityProviders) List

func (r *IdentityProviders) List(ctx context.Context, enabledOnly bool) ([]*IdentityProvider, error)

List returns providers ordered by sort_order, id; enabledOnly filters.

func (*IdentityProviders) Update

Update writes every column of p, including ClientSecretEnc.

type LDAPSettings added in v0.7.0

type LDAPSettings struct {
	Enabled              bool             `json:"enabled"`
	ServerURL            string           `json:"server_url"`
	StartTLS             bool             `json:"start_tls"`
	InsecureSkipVerify   bool             `json:"insecure_skip_verify"`
	BindDN               string           `json:"bind_dn"`
	BindPasswordEnc      []byte           `json:"-"`
	HasBindPassword      bool             `json:"has_bind_password"`
	BaseDN               string           `json:"base_dn"`
	UserSearchBase       string           `json:"user_search_base"`
	UserFilter           string           `json:"user_filter"`
	UsernameAttribute    string           `json:"username_attribute"`
	DisplayNameAttribute string           `json:"display_name_attribute"`
	EmailAttribute       string           `json:"email_attribute"`
	GroupAttribute       string           `json:"group_attribute"`
	GroupMappings        map[string]int64 `json:"group_mappings"`
	DefaultUserGroupID   *int64           `json:"default_user_group_id"`
	DefaultUserGroupName string           `json:"default_user_group_name,omitempty"`
	AutoRegister         bool             `json:"auto_register"`
	SyncIntervalMins     int              `json:"sync_interval_mins"`
	LastSyncAt           *time.Time       `json:"last_sync_at"`
	LastSyncStatus       string           `json:"last_sync_status"`
	LastSyncCount        int              `json:"last_sync_count"`
	UpdatedAt            time.Time        `json:"updated_at"`
}

LDAPSettings models the single-row ldap_settings configuration.

type LDAPSettingsRepo added in v0.7.0

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

LDAPSettingsRepo is the repository for LDAP configuration.

func (*LDAPSettingsRepo) Get added in v0.7.0

Get returns the effective LDAP configuration.

func (*LDAPSettingsRepo) Update added in v0.7.0

func (r *LDAPSettingsRepo) Update(ctx context.Context, s *LDAPSettings) error

Update saves the LDAP configuration. When s.BindPasswordEnc is nil, the existing password is kept.

func (*LDAPSettingsRepo) UpdateSyncResult added in v0.7.0

func (r *LDAPSettingsRepo) UpdateSyncResult(ctx context.Context, at time.Time, status string, count int) error

UpdateSyncResult records the timestamp, status and user count of a sync run.

type LegacyEntry

type LegacyEntry struct {
	RustdeskID string
	Patch      ABEntryPatch
}

LegacyEntry is one peer of a legacy address-book blob.

type ListDevicesParams

type ListDevicesParams struct {
	Scope DeviceScope
	// DeviceGroupID limits to one device group.
	DeviceGroupID *int64
	// Query matches RustDesk ID, hostname, alias or OS username (substring).
	Query  string
	Limit  int
	Offset int
}

ListDevicesParams filters and pages List.

type ListUsersParams

type ListUsersParams struct {
	// Query matches username, email or display name (substring, case-insensitive).
	Query       string
	Role        Role
	Status      UserStatus
	UserGroupID *int64
	Limit       int
	Offset      int
}

ListUsersParams filters and pages List.

type LoginEvent

type LoginEvent struct {
	ID                int64
	UserID            *int64
	UsernameAttempted string
	TokenID           *int64
	Method            string
	Result            string
	FailureReason     string
	// ClientKind: webadmin | client | webclient | RustDesk deviceInfo.type.
	ClientKind       string
	DeviceRustdeskID string
	DeviceUUID       string
	Platform         string
	IP               string
	UserAgent        string
	HiddenByUser     bool
	CreatedAt        time.Time
}

LoginEvent is a row of login_events.

type LoginEventFilter

type LoginEventFilter struct {
	UserID        *int64
	Result        string
	IncludeHidden bool
	BeforeID      int64
	Limit         int
}

LoginEventFilter selects login events (newest first, keyset paging).

type LoginEventQuery

type LoginEventQuery struct {
	AuditQuery
	UserID *int64
	// Result: success | failure | "".
	Result string
	Method string
	// WebOnly: true = panel logins (client_kind webadmin), false = client
	// logins, nil = both.
	WebOnly       *bool
	IncludeHidden bool
}

LoginEventQuery filters ListPanel.

type LoginEventRow

type LoginEventRow struct {
	*LoginEvent
	Username        string
	UserDisplayName string
}

LoginEventRow is a login event with the user joined in.

type LoginEvents

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

LoginEvents is the login_events repository.

func (*LoginEvents) Hide

func (r *LoginEvents) Hide(ctx context.Context, id, userID int64) error

Hide marks an event hidden for its user (legacy soft delete).

func (*LoginEvents) List

List returns login events matching f.

func (*LoginEvents) ListPanel

func (r *LoginEvents) ListPanel(ctx context.Context, f LoginEventQuery) ([]LoginEventRow, int, error)

ListPanel returns a page of login events and the total.

func (*LoginEvents) LoginStats

func (r *LoginEvents) LoginStats(ctx context.Context, since time.Time, userID *int64) (ok, failed int, hourly map[int64]int, err error)

LoginStats counts login events since `since` (optionally of one user): successes, failures and successes per hour (keyed by hour start, unix ms).

func (*LoginEvents) PurgeBefore

func (r *LoginEvents) PurgeBefore(ctx context.Context, cutoff time.Time) (int64, error)

PurgeBefore deletes events older than cutoff (retention).

func (*LoginEvents) Record

func (r *LoginEvents) Record(ctx context.Context, e *LoginEvent) error

Record inserts e; ID and CreatedAt are set. An empty Result is "success".

type OAuthAction

type OAuthAction string

OAuthAction is what a pending OAuth flow will do once the IdP answers.

const (
	OAuthLogin   OAuthAction = "login"
	OAuthBind    OAuthAction = "bind"
	OAuthWebAuth OAuthAction = "webauth"
)

OAuth actions (oauth_states.action).

type OAuthFlow

type OAuthFlow string

OAuthFlow says who started the flow.

const (
	// OAuthFlowClient: RustDesk app polling /api/oidc/auth-query.
	OAuthFlowClient OAuthFlow = "client"
	// OAuthFlowWeb: panel browser session.
	OAuthFlowWeb OAuthFlow = "web"
)

OAuth flows (oauth_states.flow).

type OAuthState

type OAuthState struct {
	ID               int64
	StateSHA256      []byte
	Action           OAuthAction
	Flow             OAuthFlow
	ProviderID       *int64
	PKCEVerifierEnc  []byte
	Nonce            string
	DeviceRustdeskID string
	DeviceUUID       string
	DeviceName       string
	DeviceOS         string
	DeviceType       string
	RedirectPath     string
	InitiatorUserID  *int64
	ResultUserID     *int64
	ResultError      string
	ProfileJSON      string
	// BindingSHA256 is sha256 of the browser-binding cookie (web flows).
	BindingSHA256 []byte
	// HandoffExpiresAt bounds the hand-off ticket (web flows, after the callback).
	HandoffExpiresAt *time.Time
	ConsumedAt       *time.Time
	CreatedAt        time.Time
	ExpiresAt        time.Time
}

OAuthState is a row of oauth_states. The plain state is never stored.

type OAuthStates

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

OAuthStates is the oauth_states repository.

func (*OAuthStates) Claim

func (r *OAuthStates) Claim(ctx context.Context, id int64) error

Claim atomically marks an active state as being processed by a callback (result_error = OAuthStateProcessing). It fails with ErrNotFound when the state is unknown, expired, consumed or already claimed, which makes every callback single-use.

func (*OAuthStates) Complete

func (r *OAuthStates) Complete(ctx context.Context, id int64, userID *int64, errMsg string) error

Complete records the outcome of a claimed state: a user id or an error.

func (*OAuthStates) Consume

func (r *OAuthStates) Consume(ctx context.Context, id int64) error

Consume atomically marks a state consumed (single use). ErrNotFound when it was already consumed or has expired.

func (*OAuthStates) Create

func (r *OAuthStates) Create(ctx context.Context, s *OAuthState) error

Create inserts s; ID and CreatedAt are set. ExpiresAt must be set by the caller.

func (*OAuthStates) GetActive

func (r *OAuthStates) GetActive(ctx context.Context, hash []byte) (*OAuthState, error)

GetActive returns the unconsumed, unexpired state with digest hash.

func (*OAuthStates) PurgeExpired

func (r *OAuthStates) PurgeExpired(ctx context.Context, cutoff time.Time) (int64, error)

PurgeExpired deletes states that expired before cutoff.

func (*OAuthStates) SetHandoff

func (r *OAuthStates) SetHandoff(ctx context.Context, id int64, profileJSON, errCode string, ticketHash []byte, expires time.Time) error

SetHandoff records the IdP result of a claimed web flow (profileJSON, or errCode when the IdP step failed) and the single-use hand-off ticket digest valid until expires.

func (*OAuthStates) SetPKCEVerifier

func (r *OAuthStates) SetPKCEVerifier(ctx context.Context, id int64, enc []byte) error

SetPKCEVerifier stores the encrypted PKCE verifier of state id (the AD contains the row id, so it is written after Create).

func (*OAuthStates) TakeHandoff

func (r *OAuthStates) TakeHandoff(ctx context.Context, ticketHash []byte) (*OAuthState, error)

TakeHandoff atomically consumes the web flow whose hand-off ticket digest is ticketHash and returns it. ErrNotFound when the ticket is unknown, expired or already used (single use: a second call always fails).

type Option

type Option func(*options)

Option configures a Store.

func WithIDGenerator

func WithIDGenerator(fn func() string) Option

WithIDGenerator replaces the random UUIDv4 generator used for public ids (address-book guids, connection-audit guids). Tests use deterministic ids.

func WithSecrets

func WithSecrets(a *crypto.AEAD) Option

WithSecrets sets the AEAD used to seal secrets that must be returned to clients (address-book passwords and hashes). Repositories that need it fail with ErrNoSecrets when it is missing.

type PresenceSamples

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

PresenceSamples records the hourly maximum of online devices.

func (*PresenceSamples) PurgeBefore

func (r *PresenceSamples) PurgeBefore(ctx context.Context, cutoff time.Time) (int64, error)

PurgeBefore deletes samples of hours before cutoff.

func (*PresenceSamples) Record

func (r *PresenceSamples) Record(ctx context.Context, at time.Time, online int) error

Record raises the sample of the hour containing at to online if higher.

func (*PresenceSamples) Since

func (r *PresenceSamples) Since(ctx context.Context, since time.Time) (map[int64]int, error)

Since returns the samples of hours starting at or after since (keyed by hour start, unix ms).

type ProviderKind

type ProviderKind string

ProviderKind is the type of an identity provider.

const (
	ProviderGitHub  ProviderKind = "github"
	ProviderGoogle  ProviderKind = "google"
	ProviderOIDC    ProviderKind = "oidc"
	ProviderLinuxDo ProviderKind = "linuxdo"
)

Identity provider kinds (identity_providers.kind).

type PunchRequest

type PunchRequest struct {
	ID           int64
	At           time.Time
	FromIP       string
	ToRustdeskID string
	ToIP         string
	CreatedAt    time.Time
}

PunchRequest is a row of punch_requests (collected from hbbs "pr").

type PunchRequests

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

PunchRequests is the punch_requests repository.

func (*PunchRequests) Insert

func (r *PunchRequests) Insert(ctx context.Context, rows []PunchRequest) error

Insert stores rows in one transaction.

func (*PunchRequests) ListPanel

func (r *PunchRequests) ListPanel(ctx context.Context, f AuditQuery) ([]PunchRequest, int, error)

ListPanel returns a page of punch requests (newest first) and the total.

type RecoveryCodes

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

RecoveryCodes is the recovery_codes repository.

func (*RecoveryCodes) CountUnused

func (r *RecoveryCodes) CountUnused(ctx context.Context, userID int64) (int, error)

CountUnused returns the number of remaining codes.

func (*RecoveryCodes) DeleteAll

func (r *RecoveryCodes) DeleteAll(ctx context.Context, userID int64) error

DeleteAll removes all codes of a user.

func (*RecoveryCodes) Replace

func (r *RecoveryCodes) Replace(ctx context.Context, userID int64, hashes [][]byte) error

Replace deletes a user's codes and stores the given digests.

func (*RecoveryCodes) Use

func (r *RecoveryCodes) Use(ctx context.Context, userID int64, hash []byte) error

Use marks the unused code with digest hash as used. ErrNotFound when no such unused code exists (wrong or already used).

type Role

type Role string

Role is a user's panel role.

const (
	RoleAdmin Role = "admin"
	RoleUser  Role = "user"
)

Roles.

type ServerShareLink struct {
	ID     int64
	UserID int64
	// Username and DisplayName are the owner's (read only).
	Username    string
	DisplayName string
	// OwnerAllowed reports whether the owner is active and may share (an
	// admin or in a user group with can_share_links); read only.
	OwnerAllowed bool
	Label        string
	TokenSHA256  []byte
	TokenEnc     []byte
	// ExpiresAt nil: permanent until revoked.
	ExpiresAt *time.Time
	// MaxDownloads nil: unlimited installer downloads.
	MaxDownloads *int
	Views        int64
	Downloads    int64
	LastUsedAt   *time.Time
	CreatedAt    time.Time
	RevokedAt    *time.Time
}

ServerShareLink is a row of server_share_links: a public link (/s/<token>) to this server's connection settings and preconfigured client. The token is stored as its sha256 (lookups) and sealed with the panel AEAD (TokenEnc, so the creator can copy the link again).

func (*ServerShareLink) Status added in v0.14.0

func (l *ServerShareLink) Status(now time.Time) ShareLinkStatus

Status returns the link's state at now. Revoked wins over expired, which wins over exhausted, which wins over suspended.

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

ServerShareLinks is the server_share_links repository.

func (*ServerShareLinks) CanShare added in v0.14.0

func (r *ServerShareLinks) CanShare(ctx context.Context, userID int64) (bool, error)

CanShare reports whether user id may create share links: an active admin, or an active user whose group has can_share_links. Unknown users: false.

func (*ServerShareLinks) CountOpen added in v0.14.0

func (r *ServerShareLinks) CountOpen(ctx context.Context, userID int64) (int, error)

CountOpen counts the links of userID that are neither revoked nor expired.

func (*ServerShareLinks) Create added in v0.14.0

Create inserts l (UserID, Label, TokenSHA256, ExpiresAt, MaxDownloads); ID and CreatedAt are set. TokenEnc is written with SetTokenEnc once the id is known (its AD contains the id).

func (*ServerShareLinks) Get added in v0.14.0

Get returns a link by id regardless of its state.

func (*ServerShareLinks) GetByHash added in v0.14.0

func (r *ServerShareLinks) GetByHash(ctx context.Context, hash []byte) (*ServerShareLink, error)

GetByHash returns the link whose token digest is hash, regardless of its state (callers check Status).

func (*ServerShareLinks) List added in v0.14.0

func (r *ServerShareLinks) List(ctx context.Context, userID *int64, limit int) ([]*ServerShareLink, error)

List returns the non-revoked links, newest first: of userID, or of every user when userID is nil. limit is clamped to 1..1000 (default 500).

func (*ServerShareLinks) RecordView added in v0.14.0

func (r *ServerShareLinks) RecordView(ctx context.Context, id int64) error

RecordView counts one opening of the public page.

func (*ServerShareLinks) Revoke added in v0.14.0

func (r *ServerShareLinks) Revoke(ctx context.Context, id int64) error

Revoke marks a link revoked (idempotent); unknown ids return ErrNotFound.

func (*ServerShareLinks) SetTokenEnc added in v0.14.0

func (r *ServerShareLinks) SetTokenEnc(ctx context.Context, id int64, enc []byte) error

SetTokenEnc stores the sealed token of link id.

func (*ServerShareLinks) TakeDownload added in v0.14.0

func (r *ServerShareLinks) TakeDownload(ctx context.Context, id int64) (bool, error)

TakeDownload counts one installer download when the link is neither revoked, expired nor out of downloads, atomically; false means refused.

type Settings

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

Settings is the key/value settings repository (JSON values).

func (*Settings) All

func (r *Settings) All(ctx context.Context) (map[string]json.RawMessage, error)

All returns every setting as raw JSON.

func (*Settings) ClientTokenLifetimes

func (r *Settings) ClientTokenLifetimes(ctx context.Context, cfgToken, cfgJWT time.Duration) (token, jwt time.Duration)

ClientTokenLifetimes returns the sliding lifetime of client tokens and the fixed JWT lifetime. The auth.client_token_lifetime_hours setting overrides cfgToken; the JWT lifetime follows it unless the configuration sets a different one (cfgJWT != cfgToken).

func (*Settings) Delete

func (r *Settings) Delete(ctx context.Context, key string) error

Delete removes key (no error when absent).

func (*Settings) Get

func (r *Settings) Get(ctx context.Context, key string, dst any) error

Get unmarshals the value of key into dst; ErrNotFound when unset.

func (*Settings) GetRaw

func (r *Settings) GetRaw(ctx context.Context, key string) (json.RawMessage, error)

GetRaw returns the raw JSON value of key; ErrNotFound when unset.

func (*Settings) PasswordLoginAllowed

func (r *Settings) PasswordLoginAllowed(ctx context.Context, u *User) (bool, error)

PasswordLoginAllowed reports whether u may sign in with a password: the auth.password_login_enabled setting (default true) applies to the user role; admins can always use their password (break-glass access).

func (*Settings) RetentionDays

func (r *Settings) RetentionDays(ctx context.Context) (map[string]int, error)

RetentionDays returns the retention of every category: the retention.<category>_days settings written by PATCH /settings, else RetentionDefaults. 0 keeps rows forever. This is the single source of truth for the settings API and the janitor.

func (*Settings) Set

func (r *Settings) Set(ctx context.Context, key string, value any, updatedBy *int64) error

Set stores value (JSON-encoded) under key. updatedBy may be nil (CLI/system).

type ShareLinkStatus added in v0.14.0

type ShareLinkStatus string

ShareLinkStatus is the effective state of a server share link.

const (
	ShareLinkActive  ShareLinkStatus = "active"
	ShareLinkExpired ShareLinkStatus = "expired"
	// ShareLinkExhausted: the installer download limit is reached.
	ShareLinkExhausted ShareLinkStatus = "exhausted"
	ShareLinkRevoked   ShareLinkStatus = "revoked"
	// ShareLinkSuspended: the owner is disabled or may no longer share
	// (neither an admin nor in a user group with can_share_links).
	ShareLinkSuspended ShareLinkStatus = "suspended"
)

Server share link states.

type SharedBook

type SharedBook struct {
	*AddressBook
	Rule ABPermission
}

SharedBook is a non-personal book visible to a user with its effective rule.

type Store

type Store struct {
	Users      *Users
	UserGroups *UserGroups
	AuthTokens *AuthTokens
	Settings   *Settings
	AdminAudit *AdminAudit

	Devices            *Devices
	DeviceGroups       *DeviceGroups
	AddressBooks       *AddressBooks
	ConnectionAudits   *ConnectionAudits
	FileTransferAudits *FileTransferAudits
	AlarmAudits        *AlarmAudits
	AuditNonces        *AuditNonces
	LoginEvents        *LoginEvents
	// Identity / OIDC / 2FA (stream B1).
	IdentityProviders *IdentityProviders
	UserIdentities    *UserIdentities
	OAuthStates       *OAuthStates
	TOTPSecrets       *TOTPSecrets
	RecoveryCodes     *RecoveryCodes
	// PunchRequests holds hbbs punch requests collected by the panel (stream B2b).
	PunchRequests *PunchRequests
	// Passkeys (WebAuthn) for panel login.
	WebAuthnCredentials *WebAuthnCredentials
	WebAuthnChallenges  *WebAuthnChallenges
	// APITokens are personal tokens for the admin API.
	APITokens *APITokens
	// ClientStrategies manages client MDM configuration strategies.
	ClientStrategies *ClientStrategies
	// ControlRoles and ConnectionACLs manage remote session permissions and access matrix.
	ControlRoles   *ControlRoles
	ConnectionACLs *ConnectionACLs
	// LDAPSettings manages directory service configuration.
	LDAPSettings *LDAPSettingsRepo
	// TerminalShells remembers web client terminal sessions kept on devices.
	TerminalShells *TerminalShells
	// ServerShareLinks are the public "connect to this server" links (/s/...).
	ServerShareLinks *ServerShareLinks
	// contains filtered or unexported fields
}

Store groups the repositories. A Store obtained from Tx is bound to that transaction and must not be used after the callback returns.

func New

func New(d *db.DB, opts ...Option) *Store

New returns a Store backed by d.

func (*Store) Assets

func (s *Store) Assets() *Assets

Assets returns the panel_assets repository bound to s.

func (*Store) EmailCodes

func (s *Store) EmailCodes() *EmailCodes

EmailCodes returns the email_codes repository bound to s.

func (*Store) NewID

func (s *Store) NewID() string

NewID returns a fresh public id from the configured generator.

func (*Store) Now

func (s *Store) Now() time.Time

Now returns the store clock's current time.

func (*Store) PresenceSamples

func (s *Store) PresenceSamples() *PresenceSamples

PresenceSamples returns the presence_samples repository bound to s.

func (*Store) PurgeRetention

func (s *Store) PurgeRetention(ctx context.Context, now time.Time) (map[string]int64, error)

PurgeRetention deletes audit rows older than each category's retention (open connections are kept for twice the retention) and returns the number of deleted rows per category.

func (*Store) Querier

func (s *Store) Querier() db.Querier

Querier exposes the underlying querier (the DB or the current transaction) for repositories defined outside this package.

func (*Store) Tx

func (s *Store) Tx(ctx context.Context, fn func(tx *Store) error) error

Tx runs fn with a Store bound to a single transaction. Calling Tx on a transactional Store runs fn in the existing transaction (no nesting).

func (*Store) WithClock

func (s *Store) WithClock(now func() time.Time) *Store

WithClock returns a copy of s using now for timestamps (tests).

type Sysinfo

type Sysinfo struct {
	// UUID replaces the stored uuid (callers enforce the change rules).
	UUID          string
	Hostname      string
	OS            string
	CPU           string
	Memory        string
	ClientVersion string
	// OSUsername is nil when the client omitted it (kept unchanged).
	OSUsername *string
}

Sysinfo holds the fields reported by POST /api/sysinfo.

type TOTPSecret

type TOTPSecret struct {
	UserID int64
	// SecretEnc is AEAD(base32 seed) with crypto.TOTPSecretAD(UserID).
	SecretEnc []byte
	// ConfirmedAt is nil while enrolment is pending.
	ConfirmedAt  *time.Time
	LastUsedStep int64
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

TOTPSecret is a row of totp_secrets.

func (*TOTPSecret) Confirmed

func (t *TOTPSecret) Confirmed() bool

Confirmed reports whether enrolment finished (2FA active).

type TOTPSecrets

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

TOTPSecrets is the totp_secrets repository.

func (*TOTPSecrets) Confirm

func (r *TOTPSecrets) Confirm(ctx context.Context, userID, step int64) error

Confirm activates a pending enrolment and records the step that confirmed it.

func (*TOTPSecrets) Delete

func (r *TOTPSecrets) Delete(ctx context.Context, userID int64) error

Delete removes a user's TOTP row (disable 2FA / admin reset).

func (*TOTPSecrets) Get

func (r *TOTPSecrets) Get(ctx context.Context, userID int64) (*TOTPSecret, error)

Get returns the TOTP row of a user (ErrNotFound when none).

func (*TOTPSecrets) StartEnrolment

func (r *TOTPSecrets) StartEnrolment(ctx context.Context, userID int64, secretEnc []byte) error

StartEnrolment stores a new unconfirmed seed, replacing an unconfirmed one. It returns ErrConflict when 2FA is already confirmed for the user.

func (*TOTPSecrets) UseStep

func (r *TOTPSecrets) UseStep(ctx context.Context, userID, step int64) error

UseStep records step as used if it is newer than the last used one (compare-and-set). ErrNotFound means the code was replayed concurrently.

type TerminalShell added in v0.14.0

type TerminalShell struct {
	ID         int64
	UserID     int64
	RustdeskID string
	// ServiceID is the plain service id (sealed at rest).
	ServiceID string
	Hostname  string
	Tabs      int
	CreatedAt time.Time
	UpdatedAt time.Time
}

TerminalShell is a row of terminal_shells: a set of shells a device keeps running for a web client user (its RustDesk terminal service id).

type TerminalShells added in v0.14.0

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

TerminalShells is the terminal_shells repository.

func (*TerminalShells) Delete added in v0.14.0

func (r *TerminalShells) Delete(ctx context.Context, userID int64, rustdeskID, serviceID string) error

Delete forgets a remembered session (no error when it is unknown).

func (*TerminalShells) List added in v0.14.0

func (r *TerminalShells) List(ctx context.Context, userID int64, rustdeskID string) ([]TerminalShell, error)

List returns the user's remembered sessions on a device, newest first.

func (*TerminalShells) Save added in v0.14.0

Save inserts or updates (by service id) a remembered session and keeps the newest MaxTerminalShells of the user's on that device.

type TokenKind

type TokenKind string

TokenKind distinguishes client tokens from panel sessions.

const (
	// TokenClient is a RustDesk client JWT (Authorization: Bearer).
	TokenClient TokenKind = "client"
	// TokenWeb is a panel session (opaque cookie token).
	TokenWeb TokenKind = "web"
)

Token kinds.

type User

type User struct {
	ID          int64
	Username    string
	Email       string // "" = NULL
	DisplayName string
	AvatarURL   string
	Note        string
	// PasswordHash/PasswordAlgo are both empty when the user has no local password.
	PasswordHash string
	PasswordAlgo string
	Role         Role
	Status       UserStatus
	UserGroupID  *int64
	TOTPRequired bool
	// EmailVerifiedAt is set while the current Email is verified.
	EmailVerifiedAt *time.Time
	// Email2FAEnabled: e-mail code as the second factor (opt-in, verified address only).
	Email2FAEnabled bool
	// Locale of e-mails ("" = panel default).
	Locale            string
	IsLDAP            bool
	LDAPDN            string
	PasswordChangedAt *time.Time
	LastLoginAt       *time.Time
	CreatedAt         time.Time
	UpdatedAt         time.Time
}

User is a row of the users table.

func (*User) EmailVerified

func (u *User) EmailVerified() bool

EmailVerified reports whether the user has an address and it is verified.

func (*User) HasPassword

func (u *User) HasPassword() bool

HasPassword reports whether a local password is set.

func (*User) IsActive

func (u *User) IsActive() bool

IsActive reports whether the user may log in.

func (*User) IsAdmin

func (u *User) IsAdmin() bool

IsAdmin reports whether the user has the admin role.

type UserACL added in v0.11.0

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

UserACL decides the connections of one user; it loads the rules and the user's group once (see ForUser).

func (*UserACL) Decide added in v0.11.0

func (u *UserACL) Decide(d *Device) (ACLDecision, *ConnectionACL)

Decide returns the decision for a connection of the user to d.

func (*UserACL) Filter added in v0.11.0

func (u *UserACL) Filter(devices []*Device) []*Device

Filter returns the devices the user may connect to.

func (*UserACL) Subject added in v0.11.0

func (u *UserACL) Subject(d *Device) ACLSubject

Subject is the ACLSubject of a connection of the user to d: the user owns d, or d's owner is in the user's "shared" group, for OwnerAccess.

type UserGroup

type UserGroup struct {
	ID         int64
	Name       string
	Visibility GroupVisibility
	Note       string
	// CanShareLinks lets members create public server share links (/s/...).
	CanShareLinks bool
	CreatedAt     time.Time
	UpdatedAt     time.Time
}

UserGroup is a row of user_groups.

type UserGroupRow

type UserGroupRow struct {
	*UserGroup
	MemberCount int
}

UserGroupRow is a user group with its member count.

type UserGroups

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

UserGroups is the user_groups repository.

func (*UserGroups) Create

func (r *UserGroups) Create(ctx context.Context, g *UserGroup) error

Create inserts g (honouring a preset ID for legacy import).

func (*UserGroups) Delete

func (r *UserGroups) Delete(ctx context.Context, id int64) error

Delete removes a group; members' user_group_id becomes NULL.

func (*UserGroups) Get

func (r *UserGroups) Get(ctx context.Context, id int64) (*UserGroup, error)

Get returns the group with id.

func (*UserGroups) GetByName

func (r *UserGroups) GetByName(ctx context.Context, name string) (*UserGroup, error)

GetByName returns the group named name (case-insensitive).

func (*UserGroups) GetRow

func (r *UserGroups) GetRow(ctx context.Context, id int64) (*UserGroupRow, error)

GetRow returns one user group with its member count.

func (*UserGroups) List

func (r *UserGroups) List(ctx context.Context) ([]*UserGroup, error)

List returns all groups ordered by name.

func (*UserGroups) Lookup

func (r *UserGroups) Lookup(ctx context.Context, q string, limit int) ([]GroupRef, error)

Lookup returns up to limit groups whose name contains q, ordered by name.

func (*UserGroups) MemberCount

func (r *UserGroups) MemberCount(ctx context.Context, id int64) (int, error)

MemberCount returns the number of users in group id.

func (*UserGroups) Search

func (r *UserGroups) Search(ctx context.Context, p GroupSearch) ([]*UserGroupRow, int, error)

Search returns a page of user groups with member counts.

func (*UserGroups) Update

func (r *UserGroups) Update(ctx context.Context, g *UserGroup) error

Update writes name, visibility, note and can_share_links.

type UserIdentities

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

UserIdentities is the user_identities repository.

func (*UserIdentities) CountForUser

func (r *UserIdentities) CountForUser(ctx context.Context, userID int64) (int, error)

CountForUser returns how many identities a user has.

func (*UserIdentities) Create

func (r *UserIdentities) Create(ctx context.Context, u *UserIdentity) error

Create inserts u; ErrConflict when (provider, subject) is already linked.

func (*UserIdentities) DeleteForUser

func (r *UserIdentities) DeleteForUser(ctx context.Context, userID, id int64) error

DeleteForUser removes identity id only if it belongs to userID.

func (*UserIdentities) Get

func (r *UserIdentities) Get(ctx context.Context, id int64) (*UserIdentity, error)

Get returns an identity by id.

func (*UserIdentities) GetByProviderSubject

func (r *UserIdentities) GetByProviderSubject(ctx context.Context, providerID int64, subject string) (*UserIdentity, error)

GetByProviderSubject returns the identity for (providerID, subject).

func (*UserIdentities) ListForUser

func (r *UserIdentities) ListForUser(ctx context.Context, userID int64) ([]*UserIdentity, error)

ListForUser returns a user's identities ordered by id.

func (*UserIdentities) RecordLogin

func (r *UserIdentities) RecordLogin(ctx context.Context, u *UserIdentity) error

RecordLogin refreshes the IdP profile snapshot and last_login_at.

type UserIdentity

type UserIdentity struct {
	ID            int64
	UserID        int64
	ProviderID    int64
	Subject       string
	Email         string
	EmailVerified bool
	DisplayName   string
	Username      string
	AvatarURL     string
	LegacyUnionID string
	LastLoginAt   *time.Time
	CreatedAt     time.Time
	UpdatedAt     time.Time
}

UserIdentity is a row of user_identities: a local user linked to an IdP subject.

type UserRef

type UserRef struct {
	ID          int64
	Username    string
	DisplayName string
}

UserRef is the minimal user identity used by pickers and embeds.

type UserRow

type UserRow struct {
	*User
	GroupName   string
	DeviceCount int
	TOTPEnabled bool
}

UserRow is a user with the joined data of the admin users list.

type UserSearch

type UserSearch struct {
	// Query matches username, email or display name (substring).
	Query       string
	Role        Role
	Status      UserStatus
	UserGroupID *int64
	// Sort: username (default), created_at, last_login_at, role.
	Sort   string
	Desc   bool
	Limit  int
	Offset int
}

UserSearch filters, sorts and pages Users.Search.

type UserStatus

type UserStatus string

UserStatus is whether a user may log in.

const (
	UserActive   UserStatus = "active"
	UserDisabled UserStatus = "disabled"
)

User statuses.

type Users

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

Users is the users repository.

func (*Users) Count

func (r *Users) Count(ctx context.Context) (int, error)

Count returns the number of users.

func (*Users) CountActiveAdmins

func (r *Users) CountActiveAdmins(ctx context.Context) (int, error)

CountActiveAdmins returns the number of enabled admins (last-admin protection).

func (*Users) Create

func (r *Users) Create(ctx context.Context, u *User) error

Create inserts u. When u.ID is non-zero it is used as-is (legacy import); otherwise an id is assigned. ID, CreatedAt and UpdatedAt are set on u.

func (*Users) Delete

func (r *Users) Delete(ctx context.Context, id int64) error

Delete removes a user (tokens, identities, books cascade).

func (*Users) GetByID

func (r *Users) GetByID(ctx context.Context, id int64) (*User, error)

GetByID returns the user with id.

func (*Users) GetByLDAPDN added in v0.7.0

func (r *Users) GetByLDAPDN(ctx context.Context, dn string) (*User, error)

GetByLDAPDN returns the user with ldap_dn (exact match).

func (*Users) GetByUsername

func (r *Users) GetByUsername(ctx context.Context, username string) (*User, error)

GetByUsername returns the user with username (case-insensitive).

func (*Users) GetRow

func (r *Users) GetRow(ctx context.Context, id int64) (*UserRow, error)

GetRow returns one user with list data.

func (*Users) List

func (r *Users) List(ctx context.Context, p ListUsersParams) ([]*User, int, error)

List returns a page of users ordered by id and the total match count.

func (*Users) ListByEmail

func (r *Users) ListByEmail(ctx context.Context, email string) ([]*User, error)

ListByEmail returns users whose email equals email (case-insensitive). Used for OIDC linking by verified email; callers must refuse ambiguous matches.

func (*Users) Lookup

func (r *Users) Lookup(ctx context.Context, q string, limit int) ([]UserRef, error)

Lookup returns up to limit active users whose username, display name or email contains q, ordered by username.

func (*Users) Refs

func (r *Users) Refs(ctx context.Context, ids []int64) (map[int64]UserRef, error)

Refs returns the users with the given ids keyed by id (unknown ids are absent).

func (*Users) RehashPassword

func (r *Users) RehashPassword(ctx context.Context, id int64, hash, algo string) error

RehashPassword replaces the stored hash after a successful login with an outdated algorithm; password_changed_at is left untouched.

func (*Users) Search

func (r *Users) Search(ctx context.Context, p UserSearch) ([]*UserRow, int, error)

Search returns a page of users with list data and the total match count.

func (*Users) SetEmail2FA

func (r *Users) SetEmail2FA(ctx context.Context, id int64, enabled bool) error

SetEmail2FA turns the e-mail second factor on or off. Enabling requires a verified address (ErrNotFound otherwise).

func (*Users) SetEmailVerified

func (r *Users) SetEmailVerified(ctx context.Context, id int64, email string, at *time.Time) error

SetEmailVerified marks the user's address verified (at != nil) or not. Verification applies only while the stored address equals email (case-insensitive); otherwise ErrNotFound. Clearing it also turns e-mail 2FA off.

func (*Users) SetPassword

func (r *Users) SetPassword(ctx context.Context, id int64, hash, algo string) error

SetPassword stores a new password hash (empty hash clears the password).

func (*Users) TouchLastLogin

func (r *Users) TouchLastLogin(ctx context.Context, id int64) error

TouchLastLogin records a successful login.

func (*Users) Update

func (r *Users) Update(ctx context.Context, u *User) error

Update writes the mutable profile/role fields of u (not the password, not the e-mail verification state). Changing the address (case-insensitively) clears email_verified_at and turns e-mail 2FA off: re-read the user to see the effect.

type WebAuthnChallenge

type WebAuthnChallenge struct {
	IDSHA256    []byte
	Kind        WebAuthnChallengeKind
	UserID      *int64
	TokenID     *int64
	SessionData []byte
	ExpiresAt   time.Time
}

WebAuthnChallenge is a row of webauthn_challenges.

type WebAuthnChallengeKind

type WebAuthnChallengeKind string

WebAuthnChallengeKind is webauthn_challenges.kind.

const (
	WebAuthnRegister WebAuthnChallengeKind = "register"
	WebAuthnLogin    WebAuthnChallengeKind = "login"
	WebAuthnMFA      WebAuthnChallengeKind = "mfa"
)

Ceremony kinds.

type WebAuthnChallenges

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

WebAuthnChallenges is the webauthn_challenges repository.

func (*WebAuthnChallenges) Consume

Consume deletes and returns the unexpired ceremony with digest idHash and the given kind (single use). ErrNotFound when missing or expired.

func (*WebAuthnChallenges) CountActiveAnonymous

func (r *WebAuthnChallenges) CountActiveAnonymous(ctx context.Context) (int, error)

CountActiveAnonymous purges expired ceremonies and returns the number of pending ceremonies not bound to a user (usernameless logins), which callers cap to bound unauthenticated writes.

func (*WebAuthnChallenges) Create

Create stores a pending ceremony.

type WebAuthnCredential

type WebAuthnCredential struct {
	ID              int64
	UserID          int64
	CredentialID    []byte
	PublicKey       []byte
	AttestationType string
	AAGUID          []byte
	SignCount       uint32
	CloneWarning    bool
	Transports      []string
	Attachment      string
	UserVerified    bool
	BackupEligible  bool
	BackupState     bool
	Name            string
	CreatedAt       time.Time
	UpdatedAt       time.Time
	LastUsedAt      *time.Time
}

WebAuthnCredential is a row of webauthn_credentials (a registered passkey).

type WebAuthnCredentials

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

WebAuthnCredentials is the webauthn_credentials / webauthn_user_handles repository.

func (*WebAuthnCredentials) CountForUser

func (r *WebAuthnCredentials) CountForUser(ctx context.Context, userID int64) (int, error)

CountForUser returns the number of passkeys of a user.

func (*WebAuthnCredentials) Create

Create inserts c; ID, CreatedAt and UpdatedAt are set. A duplicate credential id is ErrConflict.

func (*WebAuthnCredentials) DeleteForUser

func (r *WebAuthnCredentials) DeleteForUser(ctx context.Context, userID, id int64) error

DeleteForUser removes passkey id of user userID.

func (*WebAuthnCredentials) EnsureUserHandle

func (r *WebAuthnCredentials) EnsureUserHandle(ctx context.Context, userID int64, handle []byte) ([]byte, error)

EnsureUserHandle returns the user's handle, storing handle when none exists yet.

func (*WebAuthnCredentials) FlagClone

func (r *WebAuthnCredentials) FlagClone(ctx context.Context, id int64) error

FlagClone marks a passkey whose signature counter went backwards.

func (*WebAuthnCredentials) GetByCredentialID

func (r *WebAuthnCredentials) GetByCredentialID(ctx context.Context, credID []byte) (*WebAuthnCredential, error)

GetByCredentialID returns the passkey with the WebAuthn credential id.

func (*WebAuthnCredentials) GetForUser

func (r *WebAuthnCredentials) GetForUser(ctx context.Context, userID, id int64) (*WebAuthnCredential, error)

GetForUser returns passkey id of user userID (ErrNotFound otherwise).

func (*WebAuthnCredentials) ListForUser

func (r *WebAuthnCredentials) ListForUser(ctx context.Context, userID int64) ([]*WebAuthnCredential, error)

ListForUser returns a user's passkeys, oldest first.

func (*WebAuthnCredentials) RecordUse

func (r *WebAuthnCredentials) RecordUse(ctx context.Context, id int64, prev, signCount uint32, backupState, userVerified bool) error

RecordUse stores the state after a successful assertion: the new signature counter, the backup state and the last-use time. The update only applies while the stored counter is still prev (compare-and-set against concurrent replays of the same counter); ErrNotFound otherwise.

func (*WebAuthnCredentials) Rename

func (r *WebAuthnCredentials) Rename(ctx context.Context, userID, id int64, name string) error

Rename sets the display name of passkey id of user userID.

func (*WebAuthnCredentials) UserByHandle

func (r *WebAuthnCredentials) UserByHandle(ctx context.Context, handle []byte) (int64, error)

UserByHandle resolves a WebAuthn user handle to a user id.

func (*WebAuthnCredentials) UserHandle

func (r *WebAuthnCredentials) UserHandle(ctx context.Context, userID int64) ([]byte, error)

UserHandle returns the WebAuthn user handle of a user (ErrNotFound when none was assigned yet).

Jump to

Keyboard shortcuts

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