Documentation
¶
Overview ¶
Package auth implements core.Auth: it maps the X-Plex-Token a Plex app presents to an Ether user, and keeps the users table with per-user settings (stream limit, content rating cap, languages, sections).
A token is recognised, in order, as
- the server's own token (the owner),
- a server access token synced from plex.tv for the owner or a friend,
- any other plex.tv token, validated against plex.tv (GET /api/v2/user) and checked for access to this server (owner id, synced friend, or the server in that token's resources list).
Results of (3) are cached (positive and negative) so plex.tv is asked at most once per token per TTL; during a plex.tv outage a previously valid token keeps working for StaleTTL.
Index ¶
- func HashToken(token string) string
- func StoredIdentity(ctx context.Context, db *sql.DB, id int64) (*core.User, error)
- type Options
- type PlexTVValidator
- type Service
- func (s *Service) ActiveUser(ctx context.Context, id int64) (*core.User, error)
- func (s *Service) AllUsers(ctx context.Context) ([]UserInfo, error)
- func (s *Service) Authenticate(ctx context.Context, token string) (*core.User, error)
- func (s *Service) BootstrapOwner(ctx context.Context, p config.Plex) error
- func (s *Service) Close()
- func (s *Service) FlushSeen(ctx context.Context) error
- func (s *Service) Invalidate(token string)
- func (s *Service) IssueDelegation(ctx context.Context, userID int64) (string, error)
- func (s *Service) Owner(ctx context.Context) (*core.User, error)
- func (s *Service) SetBus(bus clusterbus.Bus)
- func (s *Service) SetOwner(ctx context.Context, a plextv.Account, serverToken string) error
- func (s *Service) SyncFriends(ctx context.Context, friends []plextv.Friend) error
- func (s *Service) UpdateUser(ctx context.Context, u core.User) error
- func (s *Service) User(ctx context.Context, id int64) (*core.User, error)
- func (s *Service) Users(ctx context.Context) ([]core.User, error)
- type UserInfo
- type Validator
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Options ¶
type Options struct {
// Validator checks unknown tokens; nil means only server and synced
// tokens are accepted.
Validator Validator
// CacheTTL is how long a plex.tv-validated token is trusted (15m).
CacheTTL time.Duration
// NegativeTTL is how long a rejected token is remembered (2m).
NegativeTTL time.Duration
// StaleTTL lets a validated token keep working this long past CacheTTL
// while plex.tv is unreachable (24h).
StaleTTL time.Duration
// MaxCacheEntries bounds the token caches (10000).
MaxCacheEntries int
// MaxConcurrentValidations bounds distinct unknown tokens being checked
// with plex.tv (16). Excess requests fail fast; cached tokens still work.
MaxConcurrentValidations int
Logger *slog.Logger
Now func() time.Time
}
Options configures the Service.
type PlexTVValidator ¶
PlexTVValidator is the production Validator.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service implements core.Auth and plextv.UserSync.
func (*Service) ActiveUser ¶
ActiveUser returns a current access snapshot, including for stream grants.
func (*Service) Authenticate ¶
Authenticate implements core.Auth.
func (*Service) BootstrapOwner ¶
BootstrapOwner creates the owner from config without network access (on startup, before plex.tv is reachable) and registers the server token.
func (*Service) FlushSeen ¶
FlushSeen persists last-seen times (call periodically and at shutdown). Every node flushes its own observations; the update only ever moves last_seen_at forward, so nodes flushing in any order keep the latest.
func (*Service) Invalidate ¶
Invalidate forgets cached validations of token.
func (*Service) IssueDelegation ¶ added in v0.2.7
IssueDelegation creates a server-local credential, never a plex.tv account token. Only hashes persist; expiry and membership are checked on every use, including when another cluster node receives the credential.
func (*Service) SetBus ¶
func (s *Service) SetBus(bus clusterbus.Bus)
SetBus connects the cluster bus (nil disconnects): after every write this service tells the other nodes to reload users and tokens, and it reloads when they write. A standalone server never calls it.
func (*Service) SetOwner ¶
SetOwner implements plextv.UserSync: it makes a the owner and registers serverToken as the owner's token. A unique index admits one owner row, so when another node changes the owner concurrently the losing transaction is retried against the winner's committed state.
func (*Service) SyncFriends ¶
SyncFriends implements plextv.UserSync: it replaces the synced access tokens, upserts friends' profiles (never their Ether settings) and deactivates every non-owner absent from the authoritative membership list, including viewers first discovered through personal-token validation.
func (*Service) UpdateUser ¶
UpdateUser implements core.Auth. It changes only per-user settings: stream limit, content rating cap, languages and allowed sections. Identity fields come from plex.tv and are ignored.
type UserInfo ¶
type UserInfo struct {
core.User
Active bool `json:"active"`
Origin string `json:"origin"`
Home bool `json:"home"`
Restricted bool `json:"restricted"`
PlexSections []int `json:"plexSections"`
LastSeen time.Time `json:"lastSeen,omitempty"`
}
UserInfo is a user plus bookkeeping for the admin UI.
type Validator ¶
type Validator interface {
// Account returns the account behind token. An error matching
// core.ErrUnauthorized means the token is invalid; other errors mean
// plex.tv could not answer.
Account(ctx context.Context, token string) (*plextv.Account, error)
// HasServer reports whether token's resources list includes this
// server (i.e. the account was granted access).
HasServer(ctx context.Context, token string) (bool, error)
}
Validator checks tokens Ether does not already know against plex.tv.