diff --git a/app/components/rs_auth_details_modal_component.html.erb b/app/components/rs_auth_details_modal_component.html.erb
index dcb64b1..bf86eef 100644
--- a/app/components/rs_auth_details_modal_component.html.erb
+++ b/app/components/rs_auth_details_modal_component.html.erb
@@ -12,7 +12,7 @@
Access
- <%= render RsScopeListComponent.new(scopes: @auth.permissions, root: @auth.root_access?) %>
+ <%= render RsScopeListComponent.new(scopes: permissions, root: root_access?) %>
Connected devices
diff --git a/app/components/rs_auth_details_modal_component.rb b/app/components/rs_auth_details_modal_component.rb
index 0f281cc..46daa37 100644
--- a/app/components/rs_auth_details_modal_component.rb
+++ b/app/components/rs_auth_details_modal_component.rb
@@ -7,6 +7,15 @@ class RsAuthDetailsModalComponent < ViewComponent::Base
@web_app = @auth.web_app
end
+ # Reflect the union of the app's scopes, matching the card's summary.
+ def permissions
+ @authorizations.flat_map(&:permissions).uniq
+ end
+
+ def root_access?
+ (permissions & [":r", ":rw"]).any?
+ end
+
def device_name(auth)
auth.device_name.presence || "Unknown device"
end
diff --git a/spec/features/services/rs_auths_spec.rb b/spec/features/services/rs_auths_spec.rb
index 6cec9a7..7496ba0 100644
--- a/spec/features/services/rs_auths_spec.rb
+++ b/spec/features/services/rs_auths_spec.rb
@@ -112,6 +112,34 @@ RSpec.describe "Storage connected apps", type: :feature do
end
end
+ context "with one app on multiple devices and differing scopes" do
+ let!(:laptop) do
+ create_auth(client: "notes.example.com", device: firefox_ua, permissions: %w(documents:rw))
+ end
+
+ let!(:phone) do
+ create_auth(client: "notes.example.com", device: chrome_ua,
+ permissions: %w(documents:rw photos:r))
+ end
+
+ after do
+ laptop.destroy
+ phone.destroy
+ end
+
+ it "summarises the union of the app's scopes in the card and the modal" do
+ visit apps_services_storage_path
+
+ within ".rs-auth-card" do
+ expect(page).to have_content("2 devices")
+ expect(page).to have_content("2 categories")
+ end
+
+ expect(page).to have_selector("p.scope", text: "documents", visible: false)
+ expect(page).to have_selector("p.scope", text: "photos", visible: false)
+ end
+ end
+
context "without connected apps" do
it "shows the empty state" do
visit apps_services_storage_path