From 30e45d3d34b9a6f9bd37bd807af74d95bb5e9769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Tue, 3 Nov 2026 12:01:56 +0400 Subject: [PATCH] Address second-round review nits in the storage dashboard Show the union of the app's authorizations' scopes in the modal's Access section too, so it matches the card's summary, and cover the union summary with a feature spec. Part of #254 --- .../rs_auth_details_modal_component.html.erb | 2 +- .../rs_auth_details_modal_component.rb | 9 ++++++ spec/features/services/rs_auths_spec.rb | 28 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) 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