Commit Graph
1104 Commits
Author SHA1 Message Date
raucao a669bf7c9b Add storage dashboard card and per-app details modal
- Rework RsAuthComponent into a card that shows the app, its device, an
  access summary and the permission status
- Group connected apps by app and device, so repeated authorizations for
  the same app and device (e.g. after a browser update) are shown together,
  each with its own revoke action
- Add RsAuthDetailsModalComponent with the full scope list, device,
  connected tokens and permission expiry, plus Launch and Revoke actions
  (built on the existing ModalComponent)
- Add RemoteStorageAuthorization#device_name (parsed from the user agent)
  and #expired?

Part of #254
2026-11-03 11:42:31 +04:00
raucao 7bfde9eb5a Store the remoteStorage user agent as text, not varchar(255)
CI / Test (pull_request) Failing after 46s
Real-world user agents (in-app browsers, Android WebView variants) commonly
exceed 255 characters. On PostgreSQL that would raise and 500 the consent
POST and token exchange; SQLite dev/test does not enforce the limit, so it
went unnoticed. Use text columns for user_agent on both tables.

Part of #254
2026-11-03 11:42:06 +04:00
raucao 5e494eede2 Document the storage-first launch flow
Add an explicit spec for the storage-first handoff (remoteStorage spec
section 11): launching an app passes only `#remotestorage=<address>`,
never an access token. The app then runs the application-first
(now PKCE-capable) flow itself.

Part of #254
2026-11-03 11:40:59 +04:00
raucao 05e2b1abac Store per-device user agent for remoteStorage authorizations
- Add user_agent to remote_storage_authorizations and rs_authorization_codes
- Capture the browser's user agent at consent, carry it on the authorization
  code, and store it on the authorization when the code is exchanged
- Store it directly for the implicit flow too

With the reuse shortcut gone, each authorization is already a distinct
per-device token; this adds the metadata needed to label and display them.

Part of #254
2026-11-03 11:40:58 +04:00
raucao 295261b332 Address review findings in the PKCE flow
CI / Test (pull_request) Failing after 46s
- Make authorization-code redemption atomic: claim the code with a guarded
  delete inside the transaction that creates the authorization, so concurrent
  exchanges can't both issue a token (RFC 6749 4.1.3)
- Compare the token request's client_id host to the code's stored client_id
  (defense-in-depth alongside the exact redirect_uri match)
- Reject unknown response_type values with unsupported_response_type
- Validate the PKCE code_challenge (43-128 unreserved chars, S256) so a client
  can't persist an over-long or malformed challenge
- Return invalid_request for missing token-endpoint parameters, and set
  Cache-Control: no-store on error responses too
- Use the right separator when the redirect_uri already has a query string
- Look codes up through the active scope; drop the unused consume!; serialize
  permissions as JSON
- Purge abandoned authorization codes via a recurring Solid Queue task

Part of #254
2026-11-03 11:40:18 +04:00
raucao 1e69957777 Shorten the authorization code lifetime to 60 seconds
CI / Test (pull_request) Failing after 45s
The code is redeemed by the client immediately in the OAuth callback, so
a 60-second window is plenty (and matches common practice; RFC 6749 caps
authorization codes at 10 minutes).

Part of #254
2026-11-03 09:17:44 +04:00
raucao 8dd0bf10ce Add PKCE support to remoteStorage OAuth
Implements the optional OAuth 2.0 Authorization Code grant with PKCE
(RFC 7636) for remoteStorage, as described in the remoteStorage spec
(section 10.1).

- Advertise the authorization and token endpoints plus the supported
  code_challenge method (S256) in WebFinger, and bump the advertised
  spec version to draft-dejong-remotestorage-27
- Add RsAuthorizationCode: a short-lived (5 min), single-use authorization
  code stored only as a SHA256 digest
- Add RsOauthManager services for issuing and exchanging codes, including
  S256 verification
- Add a cross-origin POST /rs/oauth/token endpoint that exchanges a code
  (and code_verifier) for an access token, with CORS and no CSRF token
- Consent dialog now carries response_type / code_challenge through the
  form and redirects with the code in the query string for the code flow
- Remove the existing-token reuse shortcut so every authorization results
  in a distinct authorization (and token)

Part of #254
2026-11-03 09:17:43 +04:00
raucao bf23931822 Merge pull request 'Isolate remoteStorage Redis specs from concurrent runs' (#261) from fix/rs-redis-flake into master
CI / Test (push) Successful in 42s
Reviewed-on: #261
2026-11-03 05:13:12 +00:00
raucao 1ac5c7725a Isolate remoteStorage Redis specs from concurrent runs
CI / Test (pull_request) Successful in 42s
Release Drafter / Update release notes draft (pull_request) Successful in 3s
The specs deleted a global authorizations:* pattern from the shared
test Redis DB, so concurrent test processes could wipe each other's
keys mid-example, causing intermittent empty/mismatched set failures.

Drop all global pattern deletes and the now-unused
redis_rs_delete_keys helper. Each spec now reads or asserts only the
exact key derived from its own random token, so runs can no longer
interfere regardless of ordering or concurrency.

Also fixes a vacuous assertion in the #destroy spec, which checked
authorizations:<user.address>:* (never matching the keys, which use
user.cn), to assert the exact key is gone.
2026-11-03 09:10:45 +04:00
raucao dbf76b64b6 Merge pull request 'Docker Compose dev setup: Garage + automated bootstrap' (#250) from chore/docker-compose-setup into master
CI / Test (push) Successful in 46s
Reviewed-on: #250
Reviewed-by: Greg <greg@kosmos.org>
2026-10-12 19:12:20 +00:00
raucao 8c395ce737 Pin platform for amd64-only Docker services
CI / Test (pull_request) Successful in 45s
Release Drafter / Update release notes draft (pull_request) Successful in 10s
2026-10-12 15:33:42 +02:00
raucao 2093f67a64 Merge pull request 'Allow remote access to dev services' (#253) from dev/remote_access into chore/docker-compose-setup
CI / Test (pull_request) Successful in 45s
Reviewed-on: #253
2026-10-06 17:37:49 +00:00
raucao 695977172f Fix Liquor Cabinet performance in dev
CI / Test (pull_request) Failing after 46s
Can't handle enough requests without ThreadPool, so once you hit the
limit, requests take 5s+ (having to wait for the keepalive timeout)
2026-10-06 19:36:26 +02:00
raucao bc37df52a0 Allow remote access to dev services
CI / Test (pull_request) Successful in 46s
Release Drafter / Update release notes draft (pull_request) Successful in 19s
2026-10-06 19:34:24 +02:00
raucao 6279699c11 Switch dev object storage from MinIO to Garage
CI / Test (pull_request) Successful in 43s
MinIO no longer publishes prebuilt community images (quay.io returns
401, Docker Hub 404), so the dev setup cannot pull the image.

Use a single-node Garage instance instead, which auto-creates the
remotestorage bucket and a dev-key1 access key on first start, and
point liquor-cabinet at it.
2026-10-06 13:52:38 +00:00
raucao 0d9c580a0a Automate first-run LDAP and database setup
The documented flow started web (with Solid Queue in Puma) before the
databases existed, and required manually creating the 389ds back-end
and seeding the LDAP directory and databases. Automate it:

- add an ldap-init one-shot service that creates the 389ds back-end if
  it does not exist
- add a web entrypoint that seeds LDAP and the databases on first start,
  and runs db:prepare on later boots
- update README and AGENTS accordingly, including the reset steps
2026-10-06 13:52:38 +00:00
raucao 49c2c9feea Merge pull request 'Gate remoteStorage by serviceEnabled instead of Flipper' (#251) from bugfix/remotestorage-service-enabled into master
CI / Test (push) Failing after 41s
Reviewed-on: #251
2026-10-06 13:52:17 +00:00
raucao 465563d6a6 Merge pull request 'Fix db seeds for Solid Queue' (#249) from fix/seeds-active-job into master
CI / Test (push) Successful in 43s
Reviewed-on: #249
2026-10-06 13:38:20 +00:00
raucao 911d2a5855 Fix db seeds for Solid Queue
CI / Test (pull_request) Successful in 45s
Release Drafter / Update release notes draft (pull_request) Successful in 3s
db/seeds.rb still required "sidekiq/testing" and wrapped seeding in
Sidekiq::Testing.inline!, but Sidekiq is no longer in the bundle after
the Solid Queue migration, so `rails db:setup` failed with a LoadError.

Run the jobs triggered while seeding inline via Active Job instead,
restoring the previous behavior with the adapter the app actually uses.
2026-10-06 13:36:33 +00:00
raucao d8bba02636 Merge pull request 'Stabilize flaky remoteStorage Redis spec' (#252) from bugfix/rs-redis-spec-stabilization into master
CI / Test (push) Failing after 44s
Reviewed-on: #252
2026-10-06 13:36:20 +00:00
raucao 2419982ef5 Stabilize flaky remoteStorage Redis spec
CI / Test (pull_request) Successful in 42s
Release Drafter / Update release notes draft (pull_request) Successful in 2s
"stores a token in redis" asserted an exact count of Redis keys for the
user, but database cleanup only covers SQL and Redis keys accumulate
across examples and spec files. It also relied on a previously-run
example having created the authorization, so it failed depending on test
order and leftover state.

Clear the authorizations:* namespace before each example in the #create
group, create the authorization under test, and assert on its specific
token key instead of a global count.
2026-10-06 15:33:04 +02:00
raucao 8fae099c12 Gate remoteStorage by serviceEnabled instead of Flipper
CI / Test (pull_request) Successful in 2m4s
Release Drafter / Update release notes draft (pull_request) Successful in 2s
The admin "Default services" setting writes the LDAP serviceEnabled
attribute, but remoteStorage access was also gated behind an unused
per-user Flipper flag that nothing ever enabled, so remoteStorage was
inaccessible for everyone.

Gate remoteStorage on service_enabled? like the other services, and make
the admin toggle reflect the LDAP attribute (this also fixes it reading
current_user instead of the user being viewed). E-Mail keeps its Flipper
gate for now.
2026-10-06 15:10:00 +02:00
raucao 4536b6505c 0.11.1
CI / Test (push) Successful in 33s
v0.11.1
2026-08-10 21:53:49 -06:00
raucao 8453c38f41 Merge pull request 'Fix avatars failing to be set on ejabberd accounts' (#247) from bugfix/246-xmpp_avatar_publishing into master
CI / Test (push) Successful in 31s
Reviewed-on: #247
2026-08-11 03:37:28 +00:00
raucao 1957df3bbd Fix avatars failing to be set on XMPP accounts
CI / Test (pull_request) Successful in 32s
Release Drafter / Update release notes draft (pull_request) Successful in 3s
There's a stray `end` that prematurely closes the class
2026-08-10 21:35:28 -06:00
raucao d196c161df Force-shutdown Puma if necessary
CI / Test (push) Successful in 31s
Do it before the systemd service's timeout is reached
2026-08-10 17:24:08 -06:00
raucao 44b5a0b36b Merge pull request 'Upgrade Rails to 8.1' (#245) from chore/upgrade_rails into master
CI / Test (push) Successful in 32s
Reviewed-on: #245
2026-08-10 23:11:28 +00:00
raucao 5ebf496096 Upgrade Rails to 8.1
CI / Test (pull_request) Successful in 1m4s
Release Drafter / Update release notes draft (pull_request) Successful in 2s
2026-08-10 17:02:37 -06:00
raucao 7a63c87b03 Fix deprecation warning 2026-08-10 17:02:20 -06:00
raucao 6cc35f07eb Remove more obsolete Devise code
The initializer was a no-op override after our Devise upgrade
2026-08-10 17:01:36 -06:00
raucao 89423ecf84 Merge pull request 'Upgrade Devise to 5.0, remove obsolete workarounds' (#244) from chore/upgrade_devise into master
CI / Test (push) Successful in 31s
Reviewed-on: #244
2026-08-10 22:40:47 +00:00
raucao c79c421b89 Fix Devise Turbo Stream responses for flash messages
CI / Test (pull_request) Successful in 33s
Release Drafter / Update release notes draft (pull_request) Successful in 2s
Wire Users::DeviseController as Devise parent controller with the
Turbo-aware responder, so failed form submissions (login, password
reset) render correctly as HTML with 422 status instead of
unprocessable turbo-stream content that Turbo silently drops.

Also fixes a NameError in the responder (rendering_options ->
error_rendering_options) and removes the dead TurboController.
2026-08-10 16:37:01 -06:00
raucao 8a8d407bcc Add missing whitespace between Devise (sign-in) errors and forms
CI / Test (pull_request) Successful in 32s
2026-08-10 15:17:43 -06:00
raucao 045df94c29 Upgrade Devise to 5.0, remove workarounds
CI / Test (pull_request) Successful in 52s
2026-08-10 15:15:27 -06:00
raucao 0c667795a7 0.11.0
CI / Test (push) Successful in 33s
v0.11.0
2026-08-10 14:43:42 -06:00
greg 3517303d37 Merge pull request 'Fix after-sign-in redirect issues' (#243) from bugfix/after-signin_redirects into master
CI / Test (push) Successful in 32s
Reviewed-on: #243
Reviewed-by: Greg <greg@kosmos.org>
2026-08-10 17:43:39 +00:00
raucao 89184cd851 Redirect to root after password reset
CI / Test (pull_request) Successful in 32s
Release Drafter / Update release notes draft (pull_request) Successful in 2s
2026-08-10 11:22:03 -06:00
raucao 29a9dee1cb Consume user_return_to on sign-in 2026-08-10 11:21:59 -06:00
raucao a62d84e20a Validate rs/oauth redirect_uri before storing return URL 2026-08-10 11:21:33 -06:00
raucao 7a892fad4e Add AGENTS.md
CI / Test (push) Successful in 32s
2026-08-10 11:01:21 -06:00
raucao d60d211765 Merge pull request 'Admin users page: filter by username' (#242) from feature/admin_user_search into master
CI / Test (push) Successful in 34s
Reviewed-on: #242
2026-08-10 16:40:32 +00:00
raucao d58c995230 Admin users page: filter by username
CI / Test (pull_request) Successful in 33s
Release Drafter / Update release notes draft (pull_request) Successful in 2s
Allow admins to filter the user list/index by username (partial matches
allowed)
2026-08-10 10:36:05 -06:00
raucao 9c143bc8d6 Merge pull request 'Switch from Yarn to Bun; use Ruby 3.3.12' (#241) from dev/yarn_to_bun into master
CI / Test (push) Successful in 33s
Reviewed-on: #241
2026-08-10 00:50:19 +00:00
raucao 0d476c8a8b Re-add Node.js for CI actions
CI / Test (pull_request) Successful in 34s
Release Drafter / Update release notes draft (pull_request) Successful in 3s
2026-08-09 18:24:28 -06:00
raucao 31341fb4ce Upgrade Ruby to 3.3.12 everywhere
CI / Test (pull_request) Failing after 2s
2026-08-09 18:13:31 -06:00
raucao 39d9f9b312 Migrate everything from Yarn to Bun
No node.js or npm necessary anymore
2026-08-09 18:13:26 -06:00
raucao 8a6e733316 Merge pull request 'Show links for log-in, ToS, and Privacy Policy when logged out' (#240) from chore/login_links into master
CI / Test (push) Successful in 44s
Reviewed-on: #240
2026-08-09 20:13:39 +00:00
raucao 9f25b23e2e Show ToS and Privacy Policy links when logged out
CI / Test (pull_request) Successful in 41s
Release Drafter / Update release notes draft (pull_request) Successful in 2s
2026-08-09 14:10:25 -06:00
raucao 6a32dd5ee9 Show log-in link in header when logged out
Except on the login page itself
2026-08-09 14:10:00 -06:00
raucao b93ddd9dbd Merge pull request 'Add additional styles for rich text' (#239) from feature/rich-text into master
CI / Test (push) Successful in 41s
Reviewed-on: #239
2026-08-09 19:05:33 +00:00