New setting, ten by default, zero for no limit. Single-use links are unaffected,
they are one viewer by definition.
The catch is what happens at the ceiling. Jellyfin throws SecurityException once a
user is at MaxActiveSessions, and that was landing in the generic handler, which
marks the record failed and runs cleanup, which deletes the guest account. So
without care, adding a ceiling would mean the eleventh person to open a link kicks
out the ten already watching and destroys the link. Capacity is caught separately
now: the record goes back to the state it was in, nothing is torn down, and the
new arrival gets a 503 page inviting them to try again.
Worth being honest that this caps how many people can start watching at once, not
how many ever get in: each redemption issues its own session token that keeps
working until the link is revoked or expires. Revoke is still the hard stop.
README picks up the multi-use option, the new setting, and a section on what a
multi-use link does and does not protect, plus the known limits around the token
in the query string, the unthrottled redeem endpoint, and the tag being hidden in
the web UI only.
Opening an expired or invalid link used to dump raw problem-details
JSON at the guest. Now they get a small page matching the sign-in
look, with the same neutral wording whether the link expired or never
existed (so tokens cannot be probed by outsiders), and an automatic
redirect to the Jellyfin home page. Fixes#1.
GuestHiddenSelectors now defaults to empty instead of shipping CSS
selectors for a plugin nobody else runs. Existing installs keep their
saved value. Fixes#3.
The movie detail page's Tags section lives in its own .itemTags container,
not inside .detailsGroupItem like genres/studios/cast, so tag chips stayed
clickable for guests. Disable those links too.
The add-to-playlist and add-to-collection entries in the item's "..."
menu render with data-id="playlist"/data-id="addtocollection", not
data-action="addtoplaylist"/"addtocollection" as previously assumed —
that selector matched an unrelated list-row button and never hid the
actual menu items. Target the correct attribute so both are hidden.
Also drop the specific plugin name from the guest-hidden-selectors
description in favor of generic wording; the default selector value
is unchanged.
Hiding .headerBackButton for guests also removed the video player's back
button (same class), so a guest could not return from playback to the
movie page. Stop hiding that class; keep home/drawer/search hidden.
Cast, studio, genre and tag links on the detail page now have
pointer-events disabled for guests so they stay visible but inert
(clicking Studio no longer spins on a page the guest cannot load), and
the add-to-playlist/add-to-collection actions are hidden.
Add a GuestHiddenSelectors config field (comma-separated CSS selectors,
surfaced through GuestState since guests cannot read plugin config) so
other plugins injected UI can be suppressed for guest sessions without
code changes; defaults to hiding the AI Search elements.
Includes fix for redemption failing with DbUpdateConcurrencyException:
change the guest password before applying the user policy, since
UpdatePolicyAsync bumps the user's EF concurrency token and a stale
instance then breaks ChangePassword.