From 3dd5d7ced66c9c56b128c7cdc7897ec67661c02a Mon Sep 17 00:00:00 2001 From: John Nunemaker Date: Thu, 26 Mar 2026 16:31:03 -0400 Subject: [PATCH] Enforce read-only mode on import action The import action was missing the read_only guard that all other mutating UI actions have. This adds the server-side check and hides the import card in the settings view when in read-only mode. Co-Authored-By: Claude Opus 4.6 --- lib/flipper/ui/actions/import.rb | 1 + lib/flipper/ui/views/settings.erb | 2 ++ spec/flipper/ui/actions/import_spec.rb | 24 +++++++++++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/flipper/ui/actions/import.rb b/lib/flipper/ui/actions/import.rb index 4b82f7103..bbc94cc10 100644 --- a/lib/flipper/ui/actions/import.rb +++ b/lib/flipper/ui/actions/import.rb @@ -8,6 +8,7 @@ class Import < UI::Action route %r{\A/settings\/import/?\Z} def post + render_read_only if read_only? contents = params['file'][:tempfile].read export = Flipper::Exporters::Json::Export.new(contents: contents) flipper.import(export) diff --git a/lib/flipper/ui/views/settings.erb b/lib/flipper/ui/views/settings.erb index b9ce768ea..066acf5df 100644 --- a/lib/flipper/ui/views/settings.erb +++ b/lib/flipper/ui/views/settings.erb @@ -38,6 +38,7 @@ +<% if write_allowed? %>

Import

@@ -51,3 +52,4 @@
+<% end %> diff --git a/spec/flipper/ui/actions/import_spec.rb b/spec/flipper/ui/actions/import_spec.rb index 484ef027f..4d7ed770c 100644 --- a/spec/flipper/ui/actions/import_spec.rb +++ b/spec/flipper/ui/actions/import_spec.rb @@ -11,11 +11,12 @@ { :csrf => token, 'csrf' => token, '_csrf_token' => token } end + let(:path) { FlipperRoot.join("spec", "fixtures", "flipper_pstore_1679087600.json") } + describe "POST /settings/import" do before do flipper.enable :plausible flipper.disable :google_analytics - path = FlipperRoot.join("spec", "fixtures", "flipper_pstore_1679087600.json") post '/settings/import', { @@ -37,5 +38,26 @@ expect(last_response.status).to be(302) expect(last_response.headers['location']).to eq('/features') end + + context "when in read only mode" do + before do + allow(flipper).to receive(:read_only?) { true } + + post '/settings/import', + { + 'authenticity_token' => token, + 'file' => Rack::Test::UploadedFile.new(path, "application/json"), + }, + 'rack.session' => session + end + + it 'returns 403' do + expect(last_response.status).to be(403) + end + + it 'renders read only template' do + expect(last_response.body).to include('read only') + end + end end end