14 Commits
Author SHA1 Message Date
dtourolleandClaude Opus 5 fd08d7ea1a Set version to 0.0.3
🏗️ Build Plugin / build (push) Successful in 1m43s
🧪 Test Plugin / test (push) Successful in 37s
🚀 Release Plugin / build-and-release (push) Successful in 45s
Startup-crash fix on top of 0.0.2.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 10:46:09 +02:00
dtourolle f430d288ea Set version to 0.0.2
🏗️ Build Plugin / build (push) Successful in 34s
🧪 Test Plugin / test (push) Successful in 35s
🚀 Release Plugin / build-and-release (push) Successful in 46s
Order-independent group resolution on top of 0.0.1.
2026-07-31 09:43:12 +02:00
dtourolle 92c7dcb871 Set version to 0.0.1 and pin assembly identity for CI builds
🏗️ Build Plugin / build (push) Successful in 37s
🚀 Release Plugin / build-and-release (push) Failing after 30s
🧪 Test Plugin / test (push) Failing after 33s
The release and nightly workflows stamp a date-based version into
build.yaml (1.0.20260729.42). That build segment exceeds the 16-bit
limit AssemblyVersion and FileVersion require, so it would fail the
compile with CS7034 if it reached them.

Directory.Build.targets is imported after Directory.Build.props and is
not rewritten by CI, so pinning the assembly identity there keeps those
builds working. The manifest version is untouched - Jellyfin identifies
plugins by GUID plus manifest version, not assembly version. Verified by
building with a date-based version injected.
2026-07-29 00:17:10 +02:00
dtourolle b4134dd744 Grant shared accounts the intersection of member library access
Previously the shared account's libraries were chosen independently of
its members, so a group could see a library that one of its members was
blocked from - joining a group became a way to gain access. That was
especially sharp with auto-created groups, where no admin is in the loop.

A shared account is now granted exactly the libraries every member can
already reach. If one member is blocked from a library, no group
containing them can see it. The account is therefore always a subset of
what each member could reach alone, which is what makes creating groups
at the login screen safe to leave on by default.

Details:

- "Enable all folders" is expanded to concrete library ids before
  intersecting, since it cannot otherwise be compared with an explicit
  list. Shared accounts are always given an explicit list, never the
  all-folders permission, so newly added libraries do not silently widen
  an existing group.
- Explicitly blocked folders are subtracted even for members who
  otherwise have access to everything.
- Fails closed: an unresolvable member contributes no access rather than
  being treated as unrestricted.
- Recomputed when membership changes, and re-applied to every group at
  startup so narrowing a member's own access narrows their groups.

Drops the now-meaningless EnableAllFolders/EnabledFolders provisioning
inputs and the DynamicGroupsEnableAllFolders setting. Adds 8 tests
covering the intersection rules.
2026-07-29 00:15:32 +02:00
dtourolle 7be07d16a2 Implement Watched Together shared viewing accounts
🏗️ Build Plugin / build (push) Has been cancelled
🧪 Test Plugin / test (push) Has been cancelled
Replaces the plugin template with a working plugin that lets several
users share one viewing account while keeping their individual watched
lists accurate.

Three pieces:

- Auto-creating groups. Logging in as "alice+bob" with any named
  member's own password provisions the shared account and signs you in.
  Verified against 10.11.5: AuthenticateUser offers unmatched usernames
  to every enabled provider and re-queries afterwards, which is the hook
  this relies on. Gated on a real member password so knowing two
  usernames is not enough to create an account.

- Multi-password authentication. IRequiresResolvedUser hands us the
  resolved shared account; each member's live stored hash is checked via
  ICryptoProvider.Verify. Deliberately avoids re-entering
  UserManager.AuthenticateUser, which would trip every member's
  failed-attempt counter whenever a different member's password matched.

- One-way played-state sync. Shared account to members only, filtered to
  PlaybackFinished/TogglePlayed/Import so playback progress ticks are
  ignored. No loop guard needed: member writes carry a non-shared id.

Membership is stored as user IDs rather than re-parsed from the username,
so shared accounts can be renamed freely. The +/name collision resolves
itself because Jellyfin only consults the plugin when no local user
matches the typed name.

Targets Jellyfin 10.11.x / net9.0. Adds Gitea CI (test, build, release),
a builder image, and 34 tests covering the auth and sync rules.
2026-07-29 00:00:13 +02:00
Shadowghost 3afa1fc407 Upgrade template to 10.9.x and .NET 8 2024-10-05 17:06:23 +02:00
Odd Stråbø ccc02d3ce0 Target Jellyfin 10.8 2022-06-24 16:49:01 +02:00
crobibero 995a1dddb5 Target 10.7 2020-12-02 17:07:32 -07:00
Odd Stråbø d035c46864 Bump targetAbi 2020-07-05 13:22:49 +02:00
dkanada 65ad257ffe add changelog property 2020-05-26 22:35:31 +09:00
dkanada 888677b117 update metadata and remove deprecated checkbox method 2020-05-26 22:11:35 +09:00
Niels van Velzen 126a0eb6b6 Update to .NET 2.1 and Jellyfin 10.5 2020-03-09 21:17:32 +01:00
dkanada 644088bad2 make some readme changes 2020-01-21 13:03:21 +09:00
dkanada f4ad4dab21 add sln file and build config 2019-03-12 02:03:41 +09:00