Revoking a device redirected away from the storage dashboard, which closed the
details modal and reloaded the page. Refreshing the affected parts instead
keeps the modal open and shows the change where it happened.
- Extract the card and the modal's access list into their own components, so
either can be re-rendered without touching the modal's open state, and share
the group summaries between the components
- Derive the app's DOM ids from its client_id (the grouping key) and the device
row ids from the authorization, through one helper used by both the templates
and the controller
- Revoke one of several devices as a Turbo Stream: remove the row and refresh
the card behind the modal and the access list
- Revoke an app's last device with a redirect, so the dashboard re-renders
itself and grouping, sorting and the empty state stay in one place
- Fade the removed row out, deferring Turbo's own removal until the animation
has ended
Part of #254
- Move the app display name and a root-access helper onto
RemoteStorageAuthorization, used by both components and the controller,
removing the duplicated fallback chain and the unused OauthHelper includes
- Summarise the card's categories from the union of the app's authorizations'
scopes, so an older token with broader access is not understated
Part of #254
- One card per app (grouped by client_id) showing distinct device and
category counts; the whole card opens the details modal (with hover and
focus highlight) instead of a separate Details button
- Details modal: access list styled like the OAuth consent dialog via a
shared RsScopeListComponent, plus per-token device, connected date and
expiry, each with its own Revoke
- "folder" -> "category" in the card, modal, consent dialog and the
auth-created notification
- Make revoke a real DELETE: it was a GET link that Turbo 8's
prefetch-on-hover fired on its own, silently deleting authorizations.
Missing or foreign authorizations now return 404 instead of 500.
- Move "Launch app" to the app level
(GET /services/storage/apps/:client_id/launch); no token id in the URL
Part of #254
- 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
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
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.