From 714091085c8b76f5b7c8eb7959da1e54670a5937 Mon Sep 17 00:00:00 2001 From: not-varram Date: Tue, 17 Feb 2026 19:15:29 -0800 Subject: [PATCH 1/5] AO3-6218 Allow certain admins to access all collection and challenge pages usually reserved for owners --- app/controllers/application_controller.rb | 16 ++++++++++ .../challenge/gift_exchange_controller.rb | 6 ++-- .../challenge/prompt_meme_controller.rb | 6 ++-- .../challenge_assignments_controller.rb | 7 +++-- .../challenge_claims_controller.rb | 7 +++-- .../challenge_requests_controller.rb | 2 +- .../challenge_signups_controller.rb | 10 +++--- .../collection_items_controller.rb | 2 +- .../collection_participants_controller.rb | 6 ++-- app/controllers/collections_controller.rb | 6 ++-- .../potential_matches_controller.rb | 6 ++-- .../challenge_assignments_controller_spec.rb | 27 ++++++++++++++++ .../challenge_claims_controller_spec.rb | 23 ++++++++++++++ .../challenge_requests_controller_spec.rb | 22 +++++++++++++ .../challenge_signups_controller_spec.rb | 31 +++++++++++++++++++ .../collection_items_controller_spec.rb | 19 ++++++++++++ ...collection_participants_controller_spec.rb | 19 ++++++++++++ .../collections_controller_spec.rb | 29 +++++++++++++++++ .../gift_exchange_controller_spec.rb | 30 ++++++++++++++++++ .../potential_matches_controller_spec.rb | 29 +++++++++++++++++ .../prompt_meme_controller_spec.rb | 30 ++++++++++++++++++ 21 files changed, 311 insertions(+), 22 deletions(-) create mode 100644 spec/controllers/potential_matches_controller_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 51d7583a67b..da28006c1ca 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -335,14 +335,30 @@ def load_collection @collection = Collection.find_by(name: params[:collection_id]) if params[:collection_id] end + def privileged_collection_admin? + logged_in_as_admin? && (current_admin.roles & %w[support policy_and_abuse superadmin]).present? + end + + def users_or_privileged_collection_admin_only + logged_in? || privileged_collection_admin? || access_denied + end + def collection_maintainers_only logged_in? && @collection && @collection.user_is_maintainer?(current_user) || access_denied end + def collection_maintainers_or_privileged_admins_only + (logged_in? && @collection && @collection.user_is_maintainer?(current_user)) || privileged_collection_admin? || access_denied + end + def collection_owners_only logged_in? && @collection && @collection.user_is_owner?(current_user) || access_denied end + def collection_owners_or_privileged_admins_only + (logged_in? && @collection && @collection.user_is_owner?(current_user)) || privileged_collection_admin? || access_denied + end + def not_allowed(fallback=nil) flash[:error] = ts("Sorry, you're not allowed to do that.") redirect_to (fallback || root_path) rescue redirect_to '/' diff --git a/app/controllers/challenge/gift_exchange_controller.rb b/app/controllers/challenge/gift_exchange_controller.rb index dccf8e0a77f..faed56f1e2b 100644 --- a/app/controllers/challenge/gift_exchange_controller.rb +++ b/app/controllers/challenge/gift_exchange_controller.rb @@ -1,9 +1,11 @@ class Challenge::GiftExchangeController < ChallengesController - before_action :users_only + before_action :users_only, except: [:edit] + before_action :users_or_privileged_collection_admin_only, only: [:edit] before_action :load_collection before_action :load_challenge, except: [:new, :create] - before_action :collection_owners_only, only: [:new, :create, :edit, :update, :destroy] + before_action :collection_owners_or_privileged_admins_only, only: [:edit] + before_action :collection_owners_only, only: [:new, :create, :update, :destroy] # ACTIONS diff --git a/app/controllers/challenge/prompt_meme_controller.rb b/app/controllers/challenge/prompt_meme_controller.rb index 4415cd462e3..e639e5fb109 100644 --- a/app/controllers/challenge/prompt_meme_controller.rb +++ b/app/controllers/challenge/prompt_meme_controller.rb @@ -1,9 +1,11 @@ class Challenge::PromptMemeController < ChallengesController - before_action :users_only + before_action :users_only, except: [:edit] + before_action :users_or_privileged_collection_admin_only, only: [:edit] before_action :load_collection before_action :load_challenge, except: [:new, :create] - before_action :collection_owners_only, only: [:new, :create, :edit, :update, :destroy] + before_action :collection_owners_or_privileged_admins_only, only: [:edit] + before_action :collection_owners_only, only: [:new, :create, :update, :destroy] # ACTIONS diff --git a/app/controllers/challenge_assignments_controller.rb b/app/controllers/challenge_assignments_controller.rb index b382c2e2691..f956e53f75b 100644 --- a/app/controllers/challenge_assignments_controller.rb +++ b/app/controllers/challenge_assignments_controller.rb @@ -1,5 +1,6 @@ class ChallengeAssignmentsController < ApplicationController - before_action :users_only + before_action :users_only, except: [:index, :show] + before_action :users_or_privileged_collection_admin_only, only: [:index, :show] before_action :load_collection, except: [:index] before_action :load_challenge, except: [:index] @@ -89,7 +90,7 @@ def index return unless load_collection @challenge = @collection.challenge if @collection signup_open and return unless !@challenge.signup_open - access_denied and return unless @challenge.user_allowed_to_see_assignments?(current_user) + access_denied and return unless @challenge.user_allowed_to_see_assignments?(current_user) || privileged_collection_admin? # we temporarily are ordering by requesting pseud to avoid left join @assignments = case @@ -108,7 +109,7 @@ def index end def show - unless @challenge.user_allowed_to_see_assignments?(current_user) || @challenge_assignment.offering_pseud.user == current_user + unless @challenge.user_allowed_to_see_assignments?(current_user) || @challenge_assignment.offering_pseud.user == current_user || privileged_collection_admin? flash[:error] = ts("You aren't allowed to see that assignment!") redirect_to "/" and return end diff --git a/app/controllers/challenge_claims_controller.rb b/app/controllers/challenge_claims_controller.rb index a29fd2e3b04..dd367ac0b97 100755 --- a/app/controllers/challenge_claims_controller.rb +++ b/app/controllers/challenge_claims_controller.rb @@ -1,6 +1,7 @@ class ChallengeClaimsController < ApplicationController - before_action :users_only + before_action :users_only, except: [:index] + before_action :users_or_privileged_collection_admin_only, only: [:index] before_action :load_collection, except: [:index] before_action :collection_owners_only, except: [:index, :show, :create, :destroy] before_action :load_claim_from_id, only: [:show, :destroy] @@ -68,14 +69,14 @@ def allowed_to_destroy # ACTIONS def index - if !(@collection = Collection.find_by(name: params[:collection_id])).nil? && @collection.closed? && !@collection.user_is_maintainer?(current_user) + if !(@collection = Collection.find_by(name: params[:collection_id])).nil? && @collection.closed? && !@collection.user_is_maintainer?(current_user) && !privileged_collection_admin? flash[:notice] = ts("This challenge is currently closed to new posts.") end if params[:collection_id] return unless load_collection @challenge = @collection.challenge - not_allowed(@collection) unless user_scoped? || @challenge.user_allowed_to_see_assignments?(current_user) + not_allowed(@collection) unless user_scoped? || @challenge.user_allowed_to_see_assignments?(current_user) || privileged_collection_admin? @claims = ChallengeClaim.unposted_in_collection(@collection) @claims = @claims.where(claiming_user_id: current_user.id) if user_scoped? diff --git a/app/controllers/challenge_requests_controller.rb b/app/controllers/challenge_requests_controller.rb index 24081d93171..76ad5e158d1 100644 --- a/app/controllers/challenge_requests_controller.rb +++ b/app/controllers/challenge_requests_controller.rb @@ -7,7 +7,7 @@ def check_visibility flash.now[:notice] = ts("Collection could not be found") redirect_to "/" and return end - unless @collection.challenge_type == "PromptMeme" || (@collection.challenge_type == "GiftExchange" && @collection.challenge.user_allowed_to_see_requests_summary?(current_user)) + unless @collection.challenge_type == "PromptMeme" || privileged_collection_admin? || (@collection.challenge_type == "GiftExchange" && @collection.challenge.user_allowed_to_see_requests_summary?(current_user)) flash.now[:notice] = ts("You are not allowed to view the requests summary!") redirect_to collection_path(@collection) and return end diff --git a/app/controllers/challenge_signups_controller.rb b/app/controllers/challenge_signups_controller.rb index 16e5d264b6c..5ce418d1400 100644 --- a/app/controllers/challenge_signups_controller.rb +++ b/app/controllers/challenge_signups_controller.rb @@ -4,7 +4,8 @@ class ChallengeSignupsController < ApplicationController include ExportsHelper - before_action :users_only, except: [:summary] + before_action :users_only, except: [:summary, :index, :show] + before_action :users_or_privileged_collection_admin_only, only: [:index, :show] before_action :load_collection, except: [:index] before_action :load_challenge, except: [:index] before_action :load_signup_from_id, only: [:show, :edit, :update, :destroy, :confirm_delete] @@ -45,7 +46,7 @@ def signup_owner_only end def maintainer_or_signup_owner_only - not_allowed(@collection) and return unless (@challenge_signup.pseud.user == current_user || @collection.user_is_maintainer?(current_user)) + not_allowed(@collection) and return unless (@challenge_signup.pseud.user == current_user || @collection.user_is_maintainer?(current_user) || privileged_collection_admin?) end def not_signup_owner @@ -100,7 +101,7 @@ def index # see ExportsHelper for export_csv method respond_to do |format| format.html { - if @challenge.user_allowed_to_see_signups?(current_user) + if @challenge.user_allowed_to_see_signups?(current_user) || privileged_collection_admin? @challenge_signups = @collection.signups.joins(:pseud) if params[:query] @query = params[:query] @@ -114,7 +115,8 @@ def index end } format.csv { - if (@collection.gift_exchange? && @challenge.user_allowed_to_see_signups?(current_user)) || + if privileged_collection_admin? || + (@collection.gift_exchange? && @challenge.user_allowed_to_see_signups?(current_user)) || (@collection.prompt_meme? && @collection.user_is_maintainer?(current_user)) csv_data = self.send("#{@challenge.class.name.underscore}_to_csv") filename = "#{@collection.name}_signups_#{Time.now.strftime('%Y-%m-%d-%H%M')}.csv" diff --git a/app/controllers/collection_items_controller.rb b/app/controllers/collection_items_controller.rb index 86a70880761..54862e9ca11 100644 --- a/app/controllers/collection_items_controller.rb +++ b/app/controllers/collection_items_controller.rb @@ -10,7 +10,7 @@ class CollectionItemsController < ApplicationController def index # TODO: AO3-6507 Refactor to use send instead of case statements. - if @collection && @collection.user_is_maintainer?(current_user) + if @collection && (@collection.user_is_maintainer?(current_user) || privileged_collection_admin?) @collection_items = @collection.collection_items.include_for_works @collection_items = case params[:status] when "approved" diff --git a/app/controllers/collection_participants_controller.rb b/app/controllers/collection_participants_controller.rb index 4851a999aa3..5feb26e9924 100644 --- a/app/controllers/collection_participants_controller.rb +++ b/app/controllers/collection_participants_controller.rb @@ -1,11 +1,13 @@ class CollectionParticipantsController < ApplicationController - before_action :users_only + before_action :users_only, except: [:index] + before_action :users_or_privileged_collection_admin_only, only: [:index] before_action :load_collection before_action :load_participant, only: [:update, :destroy] before_action :allowed_to_promote, only: [:update] before_action :allowed_to_destroy, only: [:destroy] before_action :has_other_owners, only: [:update, :destroy] - before_action :collection_maintainers_only, only: [:index, :add, :update] + before_action :collection_maintainers_or_privileged_admins_only, only: [:index] + before_action :collection_maintainers_only, only: [:add, :update] cache_sweeper :collection_sweeper diff --git a/app/controllers/collections_controller.rb b/app/controllers/collections_controller.rb index 0877f89f6cf..723f5fc1c2f 100644 --- a/app/controllers/collections_controller.rb +++ b/app/controllers/collections_controller.rb @@ -1,7 +1,9 @@ class CollectionsController < ApplicationController - before_action :users_only, only: [:new, :edit, :create, :update] + before_action :users_only, only: [:new, :create, :update] + before_action :users_or_privileged_collection_admin_only, only: [:edit] before_action :load_collection_from_id, only: [:show, :edit, :update, :destroy, :confirm_delete] - before_action :collection_owners_only, only: [:edit, :update, :destroy, :confirm_delete] + before_action :collection_owners_or_privileged_admins_only, only: [:edit] + before_action :collection_owners_only, only: [:update, :destroy, :confirm_delete] before_action :check_user_status, only: [:new, :create, :edit, :update, :destroy] before_action :validate_challenge_type before_action :check_parent_visible, only: [:index] diff --git a/app/controllers/potential_matches_controller.rb b/app/controllers/potential_matches_controller.rb index 8b19c74cb5c..d18e2235d13 100644 --- a/app/controllers/potential_matches_controller.rb +++ b/app/controllers/potential_matches_controller.rb @@ -1,8 +1,10 @@ class PotentialMatchesController < ApplicationController - before_action :users_only + before_action :users_only, except: [:index, :show] + before_action :users_or_privileged_collection_admin_only, only: [:index, :show] before_action :load_collection - before_action :collection_maintainers_only + before_action :collection_maintainers_or_privileged_admins_only, only: [:index, :show] + before_action :collection_maintainers_only, except: [:index, :show] before_action :load_challenge before_action :check_assignments_not_sent before_action :check_signup_closed, only: [:generate] diff --git a/spec/controllers/challenge_assignments_controller_spec.rb b/spec/controllers/challenge_assignments_controller_spec.rb index 3e87664965e..26f740fd41e 100644 --- a/spec/controllers/challenge_assignments_controller_spec.rb +++ b/spec/controllers/challenge_assignments_controller_spec.rb @@ -452,4 +452,31 @@ end end end + + describe "admin access to assignments pages" do + let(:gift_exchange) { create(:gift_exchange, assignments_sent_at: Faker::Time.backward) } + let(:user) { other_user } + + it "allows support admins to view assignments index and individual assignment pages" do + fake_logout + fake_login_admin(create(:support_admin)) + + get :index, params: { collection_id: collection.name } + expect(response).to have_http_status(:success) + expect(response).to render_template(:index) + + get :show, params: { id: assignment.id, collection_id: collection.name } + expect(response).to have_http_status(:success) + expect(response).to render_template(:show) + end + + it "does not allow admins with other roles to view assignments index" do + fake_logout + fake_login_admin(create(:tag_wrangling_admin)) + + get :index, params: { collection_id: collection.name } + + it_redirects_to_user_login_with_error + end + end end diff --git a/spec/controllers/challenge_claims_controller_spec.rb b/spec/controllers/challenge_claims_controller_spec.rb index 56a97f9dcfa..64bf9038485 100644 --- a/spec/controllers/challenge_claims_controller_spec.rb +++ b/spec/controllers/challenge_claims_controller_spec.rb @@ -154,4 +154,27 @@ end end end + + describe "admin access to claims index" do + let(:claiming_user) { create(:user) } + let!(:claim_one) { create(:challenge_claim, collection: collection, claiming_user: claiming_user) } + let!(:claim_two) { create(:challenge_claim, collection: collection, claiming_user: create(:user)) } + + it "allows support admins to view all claims in a collection" do + fake_login_admin(create(:support_admin)) + + get :index, params: { collection_id: collection.name } + + expect(response).to have_http_status(:success) + expect(assigns(:claims)).to include(claim_one, claim_two) + end + + it "does not allow admins with other roles to view claims index" do + fake_login_admin(create(:tag_wrangling_admin)) + + get :index, params: { collection_id: collection.name } + + it_redirects_to_user_login_with_error + end + end end diff --git a/spec/controllers/challenge_requests_controller_spec.rb b/spec/controllers/challenge_requests_controller_spec.rb index 15706d4b1c4..ea9efbfd13b 100644 --- a/spec/controllers/challenge_requests_controller_spec.rb +++ b/spec/controllers/challenge_requests_controller_spec.rb @@ -16,5 +16,27 @@ expect(response.status).not_to eq(500) end end + + context "with gift exchanges where request summary is private" do + let(:challenge) { create(:gift_exchange, requests_summary_visible: false) } + let(:collection) { create(:collection, challenge: challenge) } + + it "allows support admins to view the requests summary" do + fake_login_admin(create(:support_admin)) + + get :index, params: { collection_id: collection.name } + + expect(response).to have_http_status(:success) + expect(response).to render_template(:index) + end + + it "does not allow admins with other roles to view the requests summary" do + fake_login_admin(create(:tag_wrangling_admin)) + + get :index, params: { collection_id: collection.name } + + it_redirects_to_with_notice(collection_path(collection), "You are not allowed to view the requests summary!") + end + end end end diff --git a/spec/controllers/challenge_signups_controller_spec.rb b/spec/controllers/challenge_signups_controller_spec.rb index 3a3b3bdc644..06616de6ee2 100644 --- a/spec/controllers/challenge_signups_controller_spec.rb +++ b/spec/controllers/challenge_signups_controller_spec.rb @@ -272,4 +272,35 @@ end end end + + describe "admin access to signups pages" do + it "allows support admins to view signups index and download CSV" do + fake_login_admin(create(:support_admin)) + + get :index, params: { collection_id: closed_collection.name } + expect(response).to have_http_status(:success) + expect(response).to render_template(:index) + + get :index, params: { collection_id: closed_collection.name, format: :csv } + expect(response).to have_http_status(:success) + expect(response.content_type).to include("text/csv") + end + + it "allows support admins to view individual signups" do + fake_login_admin(create(:support_admin)) + + get :show, params: { id: closed_signup.id, collection_id: closed_collection.name } + + expect(response).to have_http_status(:success) + expect(response).to render_template(:show) + end + + it "does not allow admins with other roles to view signups index" do + fake_login_admin(create(:tag_wrangling_admin)) + + get :index, params: { collection_id: closed_collection.name } + + it_redirects_to_user_login_with_error + end + end end diff --git a/spec/controllers/collection_items_controller_spec.rb b/spec/controllers/collection_items_controller_spec.rb index ec7a4065e55..4627937446a 100644 --- a/spec/controllers/collection_items_controller_spec.rb +++ b/spec/controllers/collection_items_controller_spec.rb @@ -626,4 +626,23 @@ end end end + + describe "admin access to manage items" do + it "allows support admins to view the collection items index" do + fake_login_admin(create(:support_admin)) + + get :index, params: { collection_id: collection.name } + + expect(response).to have_http_status(:success) + expect(response).to render_template(:index) + end + + it "does not allow admins with other roles to view the collection items index" do + fake_login_admin(create(:tag_wrangling_admin)) + + get :index, params: { collection_id: collection.name } + + it_redirects_to_with_error(collections_path, "You don't have permission to see that, sorry!") + end + end end diff --git a/spec/controllers/collection_participants_controller_spec.rb b/spec/controllers/collection_participants_controller_spec.rb index af5034c6d36..90434274f84 100644 --- a/spec/controllers/collection_participants_controller_spec.rb +++ b/spec/controllers/collection_participants_controller_spec.rb @@ -444,4 +444,23 @@ end end end + + describe "admin access to membership index" do + it "allows support admins to view membership" do + fake_login_admin(create(:support_admin)) + + get :index, params: { collection_id: collection.name } + + expect(response).to have_http_status(:success) + expect(response).to render_template(:index) + end + + it "does not allow admins with other roles to view membership" do + fake_login_admin(create(:tag_wrangling_admin)) + + get :index, params: { collection_id: collection.name } + + it_redirects_to_user_login_with_error + end + end end diff --git a/spec/controllers/collections_controller_spec.rb b/spec/controllers/collections_controller_spec.rb index fe38dc191eb..1917b017b10 100644 --- a/spec/controllers/collections_controller_spec.rb +++ b/spec/controllers/collections_controller_spec.rb @@ -289,4 +289,33 @@ end end end + + describe "admin access to owner pages" do + let(:collection) { create(:collection) } + + it "allows support admins to view edit" do + fake_login_admin(create(:support_admin)) + + get :edit, params: { id: collection.name } + + expect(response).to have_http_status(:success) + expect(response).to render_template(:edit) + end + + it "does not allow admins with other roles to view edit" do + fake_login_admin(create(:tag_wrangling_admin)) + + get :edit, params: { id: collection.name } + + it_redirects_to_user_login_with_error + end + + it "does not allow support admins to update" do + fake_login_admin(create(:support_admin)) + + put :update, params: { id: collection.name, collection: { title: "Changed title" } } + + it_redirects_to_user_login_with_error + end + end end diff --git a/spec/controllers/gift_exchange_controller_spec.rb b/spec/controllers/gift_exchange_controller_spec.rb index cc30ecf4fc9..5eb153210eb 100644 --- a/spec/controllers/gift_exchange_controller_spec.rb +++ b/spec/controllers/gift_exchange_controller_spec.rb @@ -120,4 +120,34 @@ it_redirects_to_with_notice(collection, "Challenge settings were deleted.") end end + + describe "admin access to challenge settings" do + it "allows support admins to view edit" do + fake_logout + fake_login_admin(create(:support_admin)) + + get :edit, params: { collection_id: collection.name } + + expect(response).to have_http_status(:success) + expect(response).to render_template(:edit) + end + + it "does not allow support admins to update settings" do + fake_logout + fake_login_admin(create(:support_admin)) + + put :update, params: { collection_id: collection.name, gift_exchange: { requests_num_required: 3 } } + + it_redirects_to_user_login_with_error + end + + it "does not allow admins with other roles to view edit" do + fake_logout + fake_login_admin(create(:tag_wrangling_admin)) + + get :edit, params: { collection_id: collection.name } + + it_redirects_to_user_login_with_error + end + end end diff --git a/spec/controllers/potential_matches_controller_spec.rb b/spec/controllers/potential_matches_controller_spec.rb new file mode 100644 index 00000000000..d5d06c4e5ee --- /dev/null +++ b/spec/controllers/potential_matches_controller_spec.rb @@ -0,0 +1,29 @@ +require "spec_helper" + +describe PotentialMatchesController do + include LoginMacros + include RedirectExpectationHelper + + let(:collection) { create(:collection, challenge: create(:gift_exchange)) } + + describe "index" do + %i[support_admin policy_and_abuse_admin superadmin].each do |admin_factory| + it "allows #{admin_factory} to view potential matches" do + fake_login_admin(create(admin_factory)) + + get :index, params: { collection_id: collection.name } + + expect(response).to have_http_status(:success) + expect(response).to render_template(:index) + end + end + + it "does not allow admins with other roles to view potential matches" do + fake_login_admin(create(:tag_wrangling_admin)) + + get :index, params: { collection_id: collection.name } + + it_redirects_to_user_login_with_error + end + end +end diff --git a/spec/controllers/prompt_meme_controller_spec.rb b/spec/controllers/prompt_meme_controller_spec.rb index f5348f26703..79e8814d733 100644 --- a/spec/controllers/prompt_meme_controller_spec.rb +++ b/spec/controllers/prompt_meme_controller_spec.rb @@ -114,4 +114,34 @@ expect(response).to redirect_to(collection) end end + + describe "admin access to challenge settings" do + it "allows support admins to view edit" do + fake_logout + fake_login_admin(create(:support_admin)) + + get :edit, params: { collection_id: collection.name } + + expect(response).to have_http_status(:success) + expect(response).to render_template(:edit) + end + + it "does not allow support admins to update settings" do + fake_logout + fake_login_admin(create(:support_admin)) + + put :update, params: { collection_id: collection.name, prompt_meme: { requests_num_required: 3 } } + + it_redirects_to_user_login_with_error + end + + it "does not allow admins with other roles to view edit" do + fake_logout + fake_login_admin(create(:tag_wrangling_admin)) + + get :edit, params: { collection_id: collection.name } + + it_redirects_to_user_login_with_error + end + end end From 69c0d42b6c96bd4cd8c89f2f2be197b6e309ccca Mon Sep 17 00:00:00 2001 From: not-varram Date: Tue, 17 Feb 2026 19:53:09 -0800 Subject: [PATCH 2/5] Fix Rubocob issues --- .../challenge/prompt_meme_controller.rb | 4 +- .../challenge_claims_controller.rb | 21 ++---- .../challenge_requests_controller.rb | 8 +-- .../challenge_signups_controller.rb | 64 +++++++++---------- .../potential_matches_controller.rb | 4 +- 5 files changed, 45 insertions(+), 56 deletions(-) diff --git a/app/controllers/challenge/prompt_meme_controller.rb b/app/controllers/challenge/prompt_meme_controller.rb index e639e5fb109..781c32b81a8 100644 --- a/app/controllers/challenge/prompt_meme_controller.rb +++ b/app/controllers/challenge/prompt_meme_controller.rb @@ -1,5 +1,4 @@ class Challenge::PromptMemeController < ChallengesController - before_action :users_only, except: [:edit] before_action :users_or_privileged_collection_admin_only, only: [:edit] before_action :load_collection @@ -15,7 +14,7 @@ def show # The new form for prompt memes is actually the challenge settings page because challenges are always created in the context of a collection. def new - if (@collection.challenge) + if @collection.challenge flash[:notice] = ts("There is already a challenge set up for this collection.") redirect_to edit_collection_prompt_meme_path(@collection) else @@ -78,5 +77,4 @@ def prompt_meme_params ] ) end - end diff --git a/app/controllers/challenge_claims_controller.rb b/app/controllers/challenge_claims_controller.rb index dd367ac0b97..256344af80d 100755 --- a/app/controllers/challenge_claims_controller.rb +++ b/app/controllers/challenge_claims_controller.rb @@ -1,5 +1,4 @@ class ChallengeClaimsController < ApplicationController - before_action :users_only, except: [:index] before_action :users_or_privileged_collection_admin_only, only: [:index] before_action :load_collection, except: [:index] @@ -55,10 +54,10 @@ def no_user end def owner_only - unless @user == @challenge_claim.claiming_user - flash[:error] = ts("You aren't the claimer of that prompt.") - redirect_to "/" and return false - end + return if @user == @challenge_claim.claiming_user + + flash[:error] = ts("You aren't the claimer of that prompt.") + redirect_to "/" and return false end def allowed_to_destroy @@ -69,9 +68,7 @@ def allowed_to_destroy # ACTIONS def index - if !(@collection = Collection.find_by(name: params[:collection_id])).nil? && @collection.closed? && !@collection.user_is_maintainer?(current_user) && !privileged_collection_admin? - flash[:notice] = ts("This challenge is currently closed to new posts.") - end + flash[:notice] = ts("This challenge is currently closed to new posts.") if !(@collection = Collection.find_by(name: params[:collection_id])).nil? && @collection.closed? && !@collection.user_is_maintainer?(current_user) && !privileged_collection_admin? if params[:collection_id] return unless load_collection @@ -92,12 +89,8 @@ def index elsif params[:user_id] && (@user = User.find_by(login: params[:user_id])) if current_user == @user @claims = @user.request_claims.order_by_date.unposted - if params[:posted] - @claims = @user.request_claims.order_by_date.posted - end - if params[:collection_id] && (@collection = Collection.find_by(name: params[:collection_id])) - @claims = @claims.in_collection(@collection) - end + @claims = @user.request_claims.order_by_date.posted if params[:posted] + @claims = @claims.in_collection(@collection) if params[:collection_id] && (@collection = Collection.find_by(name: params[:collection_id])) else flash[:error] = ts("You aren't allowed to see that user's claims.") redirect_to '/' and return diff --git a/app/controllers/challenge_requests_controller.rb b/app/controllers/challenge_requests_controller.rb index 76ad5e158d1..617f54df188 100644 --- a/app/controllers/challenge_requests_controller.rb +++ b/app/controllers/challenge_requests_controller.rb @@ -7,10 +7,10 @@ def check_visibility flash.now[:notice] = ts("Collection could not be found") redirect_to "/" and return end - unless @collection.challenge_type == "PromptMeme" || privileged_collection_admin? || (@collection.challenge_type == "GiftExchange" && @collection.challenge.user_allowed_to_see_requests_summary?(current_user)) - flash.now[:notice] = ts("You are not allowed to view the requests summary!") - redirect_to collection_path(@collection) and return - end + return if @collection.challenge_type == "PromptMeme" || privileged_collection_admin? || (@collection.challenge_type == "GiftExchange" && @collection.challenge.user_allowed_to_see_requests_summary?(current_user)) + + flash.now[:notice] = ts("You are not allowed to view the requests summary!") + redirect_to collection_path(@collection) and return end def index diff --git a/app/controllers/challenge_signups_controller.rb b/app/controllers/challenge_signups_controller.rb index 5ce418d1400..c786cbb8f5d 100644 --- a/app/controllers/challenge_signups_controller.rb +++ b/app/controllers/challenge_signups_controller.rb @@ -28,7 +28,7 @@ def no_challenge end def check_signup_open - signup_closed and return unless (@challenge.signup_open || @collection.user_is_maintainer?(current_user)) + signup_closed and return unless @challenge.signup_open || @collection.user_is_maintainer?(current_user) end def signup_closed @@ -46,7 +46,7 @@ def signup_owner_only end def maintainer_or_signup_owner_only - not_allowed(@collection) and return unless (@challenge_signup.pseud.user == current_user || @collection.user_is_maintainer?(current_user) || privileged_collection_admin?) + not_allowed(@collection) and return unless @challenge_signup.pseud.user == current_user || @collection.user_is_maintainer?(current_user) || privileged_collection_admin? end def not_signup_owner @@ -64,20 +64,20 @@ def load_signup_from_id end def check_pseud_ownership - if params[:challenge_signup][:pseud_id] && (pseud = Pseud.find(params[:challenge_signup][:pseud_id])) - # either you have to own the pseud, OR you have to be a mod editing after signups are closed and NOT changing the pseud - unless current_user.pseuds.include?(pseud) || (@challenge_signup && @challenge_signup.pseud == pseud && signup_closed_owner?) - flash[:error] = ts("You can't sign up with that pseud.") - redirect_to root_path and return - end - end + return unless params[:challenge_signup][:pseud_id] && (pseud = Pseud.find(params[:challenge_signup][:pseud_id])) + + # either you have to own the pseud, OR you have to be a mod editing after signups are closed and NOT changing the pseud + return if current_user.pseuds.include?(pseud) || (@challenge_signup && @challenge_signup.pseud == pseud && signup_closed_owner?) + + flash[:error] = ts("You can't sign up with that pseud.") + redirect_to root_path and return end def check_signup_in_collection - unless @challenge_signup.collection_id == @collection.id - flash[:error] = ts("Sorry, that sign-up isn't associated with that collection.") - redirect_to @collection - end + return if @challenge_signup.collection_id == @collection.id + + flash[:error] = ts("Sorry, that sign-up isn't associated with that collection.") + redirect_to @collection end #### ACTIONS @@ -101,23 +101,23 @@ def index # see ExportsHelper for export_csv method respond_to do |format| format.html { - if @challenge.user_allowed_to_see_signups?(current_user) || privileged_collection_admin? - @challenge_signups = @collection.signups.joins(:pseud) - if params[:query] - @query = params[:query] - @challenge_signups = @challenge_signups.where("pseuds.name LIKE ?", '%' + params[:query] + '%') - end - @challenge_signups = @challenge_signups.order("pseuds.name").paginate(page: params[:page], per_page: ArchiveConfig.ITEMS_PER_PAGE) - elsif params[:user_id] && (@user = User.find_by(login: params[:user_id])) - @challenge_signups = @collection.signups.by_user(current_user) - else - not_allowed(@collection) + if @challenge.user_allowed_to_see_signups?(current_user) || privileged_collection_admin? + @challenge_signups = @collection.signups.joins(:pseud) + if params[:query] + @query = params[:query] + @challenge_signups = @challenge_signups.where("pseuds.name LIKE ?", '%' + params[:query] + '%') end + @challenge_signups = @challenge_signups.order("pseuds.name").paginate(page: params[:page], per_page: ArchiveConfig.ITEMS_PER_PAGE) + elsif params[:user_id] && (@user = User.find_by(login: params[:user_id])) + @challenge_signups = @collection.signups.by_user(current_user) + else + not_allowed(@collection) + end } format.csv { if privileged_collection_admin? || - (@collection.gift_exchange? && @challenge.user_allowed_to_see_signups?(current_user)) || - (@collection.prompt_meme? && @collection.user_is_maintainer?(current_user)) + (@collection.gift_exchange? && @challenge.user_allowed_to_see_signups?(current_user)) || + (@collection.prompt_meme? && @collection.user_is_maintainer?(current_user)) csv_data = self.send("#{@challenge.class.name.underscore}_to_csv") filename = "#{@collection.name}_signups_#{Time.now.strftime('%Y-%m-%d-%H%M')}.csv" send_csv_data(csv_data, filename) @@ -163,9 +163,9 @@ def summary end def show - unless @challenge_signup.valid? - flash[:error] = ts("This sign-up is invalid. Please check your sign-ups for a duplicate or edit to fix any other problems.") - end + return if @challenge_signup.valid? + + flash[:error] = ts("This sign-up is invalid. Please check your sign-ups for a duplicate or edit to fix any other problems.") end protected @@ -187,9 +187,9 @@ def build_prompts @challenge_signup.send(prompt_type).build end end - unless notice.blank? - flash[:notice] = notice - end + return if notice.blank? + + flash[:notice] = notice end public diff --git a/app/controllers/potential_matches_controller.rb b/app/controllers/potential_matches_controller.rb index d18e2235d13..93ecfb8cc82 100644 --- a/app/controllers/potential_matches_controller.rb +++ b/app/controllers/potential_matches_controller.rb @@ -1,5 +1,4 @@ class PotentialMatchesController < ApplicationController - before_action :users_only, except: [:index, :show] before_action :users_or_privileged_collection_admin_only, only: [:index, :show] before_action :load_collection @@ -123,7 +122,7 @@ def regenerate_for_signup else PotentialMatch.regenerate_for_signup(@signup) flash[:notice] = ts("Matches are being regenerated for ") + @signup.pseud.byline + - ts(". Please allow at least 5 minutes for this process to complete before refreshing the page.") + ts(". Please allow at least 5 minutes for this process to complete before refreshing the page.") end # redirect to index redirect_to collection_potential_matches_path(@collection) @@ -144,5 +143,4 @@ def cancel_generate def show end - end From e93f335032b7cd0f67b41fadaaae47a0ef38ddd0 Mon Sep 17 00:00:00 2001 From: not-varram Date: Tue, 17 Feb 2026 20:39:26 -0800 Subject: [PATCH 3/5] fix rubocop --- .../challenge/gift_exchange_controller.rb | 17 ++- .../challenge_claims_controller.rb | 52 ++++--- .../challenge_requests_controller.rb | 11 +- .../challenge_signups_controller.rb | 134 ++++++++++-------- .../potential_matches_controller.rb | 82 ++++++----- config/locales/controllers/en.yml | 68 +++++++++ 6 files changed, 236 insertions(+), 128 deletions(-) diff --git a/app/controllers/challenge/gift_exchange_controller.rb b/app/controllers/challenge/gift_exchange_controller.rb index faed56f1e2b..08ba00e076d 100644 --- a/app/controllers/challenge/gift_exchange_controller.rb +++ b/app/controllers/challenge/gift_exchange_controller.rb @@ -1,5 +1,4 @@ class Challenge::GiftExchangeController < ChallengesController - before_action :users_only, except: [:edit] before_action :users_or_privileged_collection_admin_only, only: [:edit] before_action :load_collection @@ -13,9 +12,9 @@ def show end def new - if (@collection.challenge) - flash[:notice] = ts("There is already a challenge set up for this collection.") - # TODO this will break if the challenge isn't a gift exchange + if @collection.challenge + flash[:notice] = t("challenge.gift_exchange.already_set_up") + # TODO: this will break if the challenge isn't a gift exchange redirect_to edit_collection_gift_exchange_path(@collection) else @challenge = GiftExchange.new @@ -30,7 +29,7 @@ def create if @challenge.save @collection.challenge = @challenge @collection.save - flash[:notice] = ts('Challenge was successfully created.') + flash[:notice] = t("challenge.gift_exchange.create.success") redirect_to collection_profile_path(@collection) else render action: :new @@ -39,10 +38,10 @@ def create def update if @challenge.update(gift_exchange_params) - flash[:notice] = ts('Challenge was successfully updated.') + flash[:notice] = t("challenge.gift_exchange.update.success") # expire the cache on the signup form - ActionController::Base.new.expire_fragment('challenge_signups/new') + ActionController::Base.new.expire_fragment("challenge_signups/new") # see if we initialized the tag set redirect_to collection_profile_path(@collection) @@ -53,7 +52,7 @@ def update def destroy @challenge.destroy - flash[:notice] = 'Challenge settings were deleted.' + flash[:notice] = "Challenge settings were deleted." redirect_to @collection end @@ -96,7 +95,7 @@ def gift_exchange_params :tag_sets_to_add, :character_restrict_to_fandom, :character_restrict_to_tag_set, :relationship_restrict_to_fandom, :relationship_restrict_to_tag_set, - tag_sets_to_remove: [] + { tag_sets_to_remove: [] } ], potential_match_settings_attributes: [ :id, :num_required_prompts, :num_required_fandoms, :num_required_characters, diff --git a/app/controllers/challenge_claims_controller.rb b/app/controllers/challenge_claims_controller.rb index 256344af80d..95ccd30bd1b 100755 --- a/app/controllers/challenge_claims_controller.rb +++ b/app/controllers/challenge_claims_controller.rb @@ -9,7 +9,6 @@ class ChallengeClaimsController < ApplicationController before_action :allowed_to_destroy, only: [:destroy] - # PERMISSIONS AND STATUS CHECKING def load_challenge @@ -22,8 +21,12 @@ def load_challenge end def no_challenge - flash[:error] = ts("What challenge did you want to work with?") - redirect_to collection_path(@collection) rescue redirect_to '/' + flash[:error] = t("challenge_claims.no_challenge") + begin + redirect_to collection_path(@collection) + rescue StandardError + redirect_to "/" + end false end @@ -33,11 +36,19 @@ def load_claim_from_id end def no_claim - flash[:error] = ts("What claim did you want to work on?") + flash[:error] = t("challenge_claims.no_claim") if @collection - redirect_to collection_path(@collection) rescue redirect_to '/' + begin + redirect_to collection_path(@collection) + rescue StandardError + redirect_to "/" + end else - redirect_to user_path(@user) rescue redirect_to '/' + begin + redirect_to user_path(@user) + rescue StandardError + redirect_to "/" + end end false end @@ -48,7 +59,7 @@ def load_user end def no_user - flash[:error] = ts("What user were you trying to work with?") + flash[:error] = t("challenge_claims.no_user") redirect_to "/" and return false end @@ -56,7 +67,7 @@ def no_user def owner_only return if @user == @challenge_claim.claiming_user - flash[:error] = ts("You aren't the claimer of that prompt.") + flash[:error] = t("challenge_claims.owner_only") redirect_to "/" and return false end @@ -64,11 +75,10 @@ def allowed_to_destroy @challenge_claim.user_allowed_to_destroy?(current_user) || not_allowed(@collection) end - # ACTIONS def index - flash[:notice] = ts("This challenge is currently closed to new posts.") if !(@collection = Collection.find_by(name: params[:collection_id])).nil? && @collection.closed? && !@collection.user_is_maintainer?(current_user) && !privileged_collection_admin? + flash[:notice] = t("challenge_claims.index.challenge_closed") if !(@collection = Collection.find_by(name: params[:collection_id])).nil? && @collection.closed? && !@collection.user_is_maintainer?(current_user) && !privileged_collection_admin? if params[:collection_id] return unless load_collection @@ -81,19 +91,19 @@ def index # sorting set_sort_order - if params[:sort] == "claimer" - @claims = @claims.order_by_offering_pseud(@sort_direction) - else - @claims = @claims.order(@sort_order) - end + @claims = if params[:sort] == "claimer" + @claims.order_by_offering_pseud(@sort_direction) + else + @claims.order(@sort_order) + end elsif params[:user_id] && (@user = User.find_by(login: params[:user_id])) if current_user == @user @claims = @user.request_claims.order_by_date.unposted @claims = @user.request_claims.order_by_date.posted if params[:posted] @claims = @claims.in_collection(@collection) if params[:collection_id] && (@collection = Collection.find_by(name: params[:collection_id])) else - flash[:error] = ts("You aren't allowed to see that user's claims.") - redirect_to '/' and return + flash[:error] = t("challenge_claims.index.access_denied_user_claims") + redirect_to "/" and return end end @claims = @claims.paginate page: params[:page], per_page: ArchiveConfig.ITEMS_PER_PAGE @@ -118,18 +128,18 @@ def create def destroy redirect_path = collection_claims_path(@collection) - flash[:notice] = ts("The claim was deleted.") + flash[:notice] = t("challenge_claims.destroy.claim_deleted") if @challenge_claim.claiming_user == current_user redirect_path = collection_claims_path(@collection, for_user: true) - flash[:notice] = ts("Your claim was deleted.") + flash[:notice] = t("challenge_claims.destroy.your_claim_deleted") end begin @challenge_claim.destroy - rescue + rescue StandardError flash.delete(:notice) - flash[:error] = ts("We couldn't delete that right now, sorry! Please try again later.") + flash[:error] = t("challenge_claims.destroy.delete_failed") end redirect_to redirect_path end diff --git a/app/controllers/challenge_requests_controller.rb b/app/controllers/challenge_requests_controller.rb index 617f54df188..5fcdf3bd2c0 100644 --- a/app/controllers/challenge_requests_controller.rb +++ b/app/controllers/challenge_requests_controller.rb @@ -4,12 +4,12 @@ class ChallengeRequestsController < ApplicationController def check_visibility unless @collection - flash.now[:notice] = ts("Collection could not be found") + flash.now[:notice] = t("challenge_requests.check_visibility.collection_not_found") redirect_to "/" and return end return if @collection.challenge_type == "PromptMeme" || privileged_collection_admin? || (@collection.challenge_type == "GiftExchange" && @collection.challenge.user_allowed_to_see_requests_summary?(current_user)) - flash.now[:notice] = ts("You are not allowed to view the requests summary!") + flash.now[:notice] = t("challenge_requests.check_visibility.access_denied") redirect_to collection_path(@collection) and return end @@ -23,9 +23,10 @@ def index # actual content, do the efficient method unless we need the full query if @sort_column == "fandom" - query = "SELECT prompts.*, GROUP_CONCAT(tags.name) AS tagnames FROM prompts INNER JOIN set_taggings ON prompts.tag_set_id = set_taggings.tag_set_id - INNER JOIN tags ON tags.id = set_taggings.tag_id - WHERE prompts.type = 'Request' AND tags.type = 'Fandom' AND prompts.collection_id = " + @collection.id.to_s + " GROUP BY prompts.id ORDER BY tagnames " + @sort_direction + query = "SELECT prompts.*, GROUP_CONCAT(tags.name) AS tagnames FROM prompts INNER JOIN set_taggings ON prompts.tag_set_id = set_taggings.tag_set_id " \ + "INNER JOIN tags ON tags.id = set_taggings.tag_id " \ + "WHERE prompts.type = 'Request' AND tags.type = 'Fandom' AND prompts.collection_id = #{@collection.id} " \ + "GROUP BY prompts.id ORDER BY tagnames #{@sort_direction}" @requests = Prompt.paginate_by_sql(query, page: params[:page], per_page: ArchiveConfig.ITEMS_PER_PAGE) elsif @sort_column == "prompter" && !@collection.prompts.exists?(anonymous: true) @requests = @collection.prompts.where(type: "Request") diff --git a/app/controllers/challenge_signups_controller.rb b/app/controllers/challenge_signups_controller.rb index c786cbb8f5d..6627c172ef6 100644 --- a/app/controllers/challenge_signups_controller.rb +++ b/app/controllers/challenge_signups_controller.rb @@ -1,5 +1,5 @@ # For exporting to Excel CSV format -require 'csv' +require "csv" class ChallengeSignupsController < ApplicationController include ExportsHelper @@ -22,8 +22,12 @@ def load_challenge end def no_challenge - flash[:error] = ts("What challenge did you want to sign up for?") - redirect_to collection_path(@collection) rescue redirect_to '/' + flash[:error] = t("challenge_signups.no_challenge") + begin + redirect_to collection_path(@collection) + rescue StandardError + redirect_to "/" + end false end @@ -32,8 +36,12 @@ def check_signup_open end def signup_closed - flash[:error] = ts("Sign-up is currently closed: please contact a moderator for help.") - redirect_to @collection rescue redirect_to '/' + flash[:error] = t("challenge_signups.signup_closed") + begin + redirect_to @collection + rescue StandardError + redirect_to "/" + end false end @@ -50,7 +58,7 @@ def maintainer_or_signup_owner_only end def not_signup_owner - flash[:error] = ts("You can't edit someone else's sign-up!") + flash[:error] = t("challenge_signups.not_signup_owner") redirect_to @collection false end @@ -69,14 +77,14 @@ def check_pseud_ownership # either you have to own the pseud, OR you have to be a mod editing after signups are closed and NOT changing the pseud return if current_user.pseuds.include?(pseud) || (@challenge_signup && @challenge_signup.pseud == pseud && signup_closed_owner?) - flash[:error] = ts("You can't sign up with that pseud.") + flash[:error] = t("challenge_signups.check_pseud_ownership.invalid_pseud") redirect_to root_path and return end def check_signup_in_collection return if @challenge_signup.collection_id == @collection.id - flash[:error] = ts("Sorry, that sign-up isn't associated with that collection.") + flash[:error] = t("challenge_signups.check_signup_in_collection.signup_not_in_collection") redirect_to @collection end @@ -88,8 +96,8 @@ def index @challenge_signups = @user.challenge_signups.order_by_date render action: :index and return else - flash[:error] = ts("You aren't allowed to see that user's sign-ups.") - redirect_to '/' and return + flash[:error] = t("challenge_signups.index.access_denied_user_signups") + redirect_to "/" and return end else load_collection @@ -100,12 +108,12 @@ def index # using respond_to in order to provide Excel output # see ExportsHelper for export_csv method respond_to do |format| - format.html { + format.html do if @challenge.user_allowed_to_see_signups?(current_user) || privileged_collection_admin? @challenge_signups = @collection.signups.joins(:pseud) if params[:query] @query = params[:query] - @challenge_signups = @challenge_signups.where("pseuds.name LIKE ?", '%' + params[:query] + '%') + @challenge_signups = @challenge_signups.where("pseuds.name LIKE ?", "%#{params[:query]}%") end @challenge_signups = @challenge_signups.order("pseuds.name").paginate(page: params[:page], per_page: ArchiveConfig.ITEMS_PER_PAGE) elsif params[:user_id] && (@user = User.find_by(login: params[:user_id])) @@ -113,19 +121,23 @@ def index else not_allowed(@collection) end - } - format.csv { + end + format.csv do if privileged_collection_admin? || (@collection.gift_exchange? && @challenge.user_allowed_to_see_signups?(current_user)) || (@collection.prompt_meme? && @collection.user_is_maintainer?(current_user)) csv_data = self.send("#{@challenge.class.name.underscore}_to_csv") - filename = "#{@collection.name}_signups_#{Time.now.strftime('%Y-%m-%d-%H%M')}.csv" + filename = "#{@collection.name}_signups_#{Time.current.strftime('%Y-%m-%d-%H%M')}.csv" send_csv_data(csv_data, filename) else - flash[:error] = ts("You aren't allowed to see the CSV summary.") - redirect_to collection_path(@collection) rescue redirect_to '/' and return + flash[:error] = t("challenge_signups.index.access_denied_csv") + begin + redirect_to collection_path(@collection) + rescue StandardError + redirect_to "/" and return + end end - } + end end end @@ -134,8 +146,8 @@ def summary @summary = ChallengeSignupSummary.new(@collection) - if @collection.signups.count < (ArchiveConfig.ANONYMOUS_THRESHOLD_COUNT/2) - flash.now[:notice] = ts("Summary does not appear until at least %{count} sign-ups have been made!", count: ((ArchiveConfig.ANONYMOUS_THRESHOLD_COUNT/2))) + if @collection.signups.count < (ArchiveConfig.ANONYMOUS_THRESHOLD_COUNT / 2) + flash.now[:notice] = t("challenge_signups.summary.minimum_signups", count: ((ArchiveConfig.ANONYMOUS_THRESHOLD_COUNT / 2))) elsif @collection.signups.count > ArchiveConfig.MAX_SIGNUPS_FOR_LIVE_SUMMARY # too many signups in this collection to show the summary page "live" modification_time = @summary.cached_time @@ -165,25 +177,26 @@ def summary def show return if @challenge_signup.valid? - flash[:error] = ts("This sign-up is invalid. Please check your sign-ups for a duplicate or edit to fix any other problems.") + flash[:error] = t("challenge_signups.show.invalid_signup") end protected + def build_prompts notice = "" @challenge.class::PROMPT_TYPES.each do |prompt_type| num_to_build = params["num_#{prompt_type}"] ? params["num_#{prompt_type}"].to_i : @challenge.required(prompt_type) if num_to_build < @challenge.required(prompt_type) - notice += ts("You must submit at least %{required} #{prompt_type}. ", required: @challenge.required(prompt_type)) + notice += t("challenge_signups.build_prompts.must_submit_at_least", required: @challenge.required(prompt_type), prompt_type: prompt_type) num_to_build = @challenge.required(prompt_type) elsif num_to_build > @challenge.allowed(prompt_type) - notice += ts("You can only submit up to %{allowed} #{prompt_type}. ", allowed: @challenge.allowed(prompt_type)) + notice += t("challenge_signups.build_prompts.can_only_submit_up_to", allowed: @challenge.allowed(prompt_type), prompt_type: prompt_type) num_to_build = @challenge.allowed(prompt_type) elsif params["num_#{prompt_type}"] - notice += ts("Set up %{num} #{prompt_type.pluralize}. ", num: num_to_build) + notice += t("challenge_signups.build_prompts.set_up_num", num: num_to_build, prompt_type: prompt_type.pluralize) end num_existing = @challenge_signup.send(prompt_type).count - num_existing.upto(num_to_build-1) do + num_existing.upto(num_to_build - 1) do @challenge_signup.send(prompt_type).build end end @@ -193,10 +206,11 @@ def build_prompts end public + def new @page_subtitle = t(".page_title") if (@challenge_signup = ChallengeSignup.in_collection(@collection).by_user(current_user).first) - flash[:notice] = ts("You are already signed up for this challenge. You can edit your sign-up below.") + flash[:notice] = t("challenge_signups.new.already_signed_up") redirect_to edit_collection_signup_path(@collection, @challenge_signup) else @challenge_signup = ChallengeSignup.new @@ -215,7 +229,7 @@ def create @challenge_signup.collection = @collection # we check validity first to prevent saving tag sets if invalid if @challenge_signup.valid? && @challenge_signup.save - flash[:notice] = ts('Sign-up was successfully created.') + flash[:notice] = t("challenge_signups.create.success") redirect_to collection_signup_path(@collection, @challenge_signup) else render action: :new @@ -224,7 +238,7 @@ def create def update if @challenge_signup.update(challenge_signup_params) - flash[:notice] = ts('Sign-up was successfully updated.') + flash[:notice] = t("challenge_signups.update.success") redirect_to collection_signup_path(@collection, @challenge_signup) else render action: :edit @@ -235,11 +249,11 @@ def confirm_delete end def destroy - unless @challenge.signup_open || @collection.user_is_maintainer?(current_user) - flash[:error] = ts("You cannot delete your sign-up after sign-ups are closed. Please contact a moderator for help.") - else + if @challenge.signup_open || @collection.user_is_maintainer?(current_user) @challenge_signup.destroy - flash[:notice] = ts("Challenge sign-up was deleted.") + flash[:notice] = t("challenge_signups.destroy.success") + else + flash[:error] = t("challenge_signups.destroy.signups_closed") end if @collection.user_is_maintainer?(current_user) && !@collection.prompt_meme? redirect_to collection_signups_path(@collection) @@ -250,17 +264,21 @@ def destroy end end - -protected + protected def request_to_array(type, request) - any_types = TagSet::TAG_TYPES.select {|type| request && request.send("any_#{type}")} - any_types.map! { |type| ts("Any %{type}", type: type.capitalize) } - tags = request.nil? ? [] : request.tag_set.tags.map {|tag| tag.name} + any_types = TagSet::TAG_TYPES.select { |tag_type| request&.send("any_#{tag_type}") } + any_types.map! { |tag_type| t("challenge_signups.request_to_array.any_type", type: tag_type.capitalize) } + tags = request.nil? ? [] : request.tag_set.tags.map(&:name) rarray = [(tags + any_types).join(", ")] if @challenge.send("#{type}_restriction").optional_tags_allowed - rarray << (request.nil? ? "" : request.optional_tag_set.tags.map {|tag| tag.name}.join(", ")) + rarray << (if request.nil? + "" + else + request.optional_tag_set.tags.map(&:name) + .join(", ") + end) end if @challenge.send("#{type}_restriction").title_allowed @@ -280,23 +298,22 @@ def request_to_array(type, request) rarray << (request.nil? ? "" : request.url) if @challenge.send("#{type}_restriction").url_allowed - return rarray + rarray end - def gift_exchange_to_csv header = ["Pseud", "Email", "Sign-up URL"] - %w(request offer).each do |type| + %w[request offer].each do |type| @challenge.send("#{type.pluralize}_num_allowed").times do |i| - header << "#{type.capitalize} #{i+1} Tags" - header << "#{type.capitalize} #{i+1} Optional Tags" if + header << "#{type.capitalize} #{i + 1} Tags" + header << "#{type.capitalize} #{i + 1} Optional Tags" if @challenge.send("#{type}_restriction").optional_tags_allowed - header << "#{type.capitalize} #{i+1} Title" if + header << "#{type.capitalize} #{i + 1} Title" if @challenge.send("#{type}_restriction").title_allowed - header << "#{type.capitalize} #{i+1} Description" if + header << "#{type.capitalize} #{i + 1} Description" if @challenge.send("#{type}_restriction").description_allowed - header << "#{type.capitalize} #{i+1} URL" if + header << "#{type.capitalize} #{i + 1} URL" if @challenge.send("#{type}_restriction").url_allowed end end @@ -308,7 +325,7 @@ def gift_exchange_to_csv row = [signup.pseud.name, signup.pseud.user.email, collection_signup_url(@collection, signup)] - %w(request offer).each do |type| + %w[request offer].each do |type| @challenge.send("#{type.pluralize}_num_allowed").times do |i| row += request_to_array(type, signup.send(type.pluralize)[i]) end @@ -319,7 +336,6 @@ def gift_exchange_to_csv csv_array end - def prompt_meme_to_csv header = ["Pseud", "Sign-up URL", "Tags"] header << "Optional Tags" if @challenge.request_restriction.optional_tags_allowed @@ -368,7 +384,7 @@ def nested_prompt_params :anonymous, :description, :_destroy, - tag_set_attributes: [ + { tag_set_attributes: [ :id, :updated_at, :character_tagnames, @@ -378,17 +394,17 @@ def nested_prompt_params :rating_tagnames, :archive_warning_tagnames, :fandom_tagnames, - character_tagnames: [], - relationship_tagnames: [], - freeform_tagnames: [], - category_tagnames: [], - rating_tagnames: [], - archive_warning_tagnames: [], - fandom_tagnames: [], + { character_tagnames: [], + relationship_tagnames: [], + freeform_tagnames: [], + category_tagnames: [], + rating_tagnames: [], + archive_warning_tagnames: [], + fandom_tagnames: [] } ], - optional_tag_set_attributes: [ - :tagnames - ] + optional_tag_set_attributes: [ + :tagnames + ] } ] end end diff --git a/app/controllers/potential_matches_controller.rb b/app/controllers/potential_matches_controller.rb index 93ecfb8cc82..eaed9f16f0d 100644 --- a/app/controllers/potential_matches_controller.rb +++ b/app/controllers/potential_matches_controller.rb @@ -9,15 +9,18 @@ class PotentialMatchesController < ApplicationController before_action :check_signup_closed, only: [:generate] before_action :load_potential_match_from_id, only: [:show] - def load_challenge @challenge = @collection.challenge no_challenge and return unless @challenge end def no_challenge - flash[:error] = ts("What challenge did you want to sign up for?") - redirect_to collection_path(@collection) rescue redirect_to '/' + flash[:error] = t("potential_matches.no_challenge") + begin + redirect_to collection_path(@collection) + rescue StandardError + redirect_to "/" + end false end @@ -27,18 +30,26 @@ def load_potential_match_from_id end def no_assignment - flash[:error] = ts("What potential match did you want to work on?") - redirect_to collection_path(@collection) rescue redirect_to '/' + flash[:error] = t("potential_matches.no_assignment") + begin + redirect_to collection_path(@collection) + rescue StandardError + redirect_to "/" + end false end def check_signup_closed - signup_open and return unless !@challenge.signup_open + signup_open and return if @challenge.signup_open end def signup_open - flash[:error] = ts("Sign-up is still open, you cannot determine potential matches now.") - redirect_to @collection rescue redirect_to '/' + flash[:error] = t("potential_matches.signup_open") + begin + redirect_to @collection + rescue StandardError + redirect_to "/" + end false end @@ -47,8 +58,12 @@ def check_assignments_not_sent end def assignments_sent - flash[:error] = ts("Assignments have already been sent! If necessary, you can purge them.") - redirect_to collection_assignments_path(@collection) rescue redirect_to '/' + flash[:error] = t("potential_matches.assignments_sent") + begin + redirect_to collection_assignments_path(@collection) + rescue StandardError + redirect_to "/" + end false end @@ -64,9 +79,9 @@ def index @progress = PotentialMatch.progress(@collection) elsif ChallengeAssignment.in_progress?(@collection) @assignment_in_progress = true - elsif @collection.potential_matches.count > 0 && @collection.assignments.count == 0 - flash[:error] = ts("There has been an error in the potential matching. Please first try regenerating assignments, and if that doesn't work, all potential matches. If the problem persists, please contact Support.") - elsif @collection.potential_matches.count > 0 + elsif @collection.potential_matches.count.positive? && @collection.assignments.count.zero? + flash[:error] = t("potential_matches.index.matching_error") + elsif @collection.potential_matches.count.positive? # we have potential_matches and assignments ### find assignments with no potential recipients @@ -80,19 +95,19 @@ def index @assignments_with_no_potential_givers = @collection.assignments.where(request_signup_id: no_rpms) # list the assignments by requester - if params[:no_giver] - @assignments = @collection.assignments.with_request.with_no_offer.order_by_requesting_pseud - elsif params[:no_recipient] - # ordering causes this to hang on large challenge due to - # left join required to get offering pseuds - @assignments = @collection.assignments.with_offer.with_no_request # .order_by_offering_pseud - elsif params[:dup_giver] - @assignments = ChallengeAssignment.duplicate_givers(@collection).order_by_offering_pseud - elsif params[:dup_recipient] - @assignments = ChallengeAssignment.duplicate_recipients(@collection).order_by_requesting_pseud - else - @assignments = @collection.assignments.with_request.with_offer.order_by_requesting_pseud - end + @assignments = if params[:no_giver] + @collection.assignments.with_request.with_no_offer.order_by_requesting_pseud + elsif params[:no_recipient] + # ordering causes this to hang on large challenge due to + # left join required to get offering pseuds + @collection.assignments.with_offer.with_no_request # .order_by_offering_pseud + elsif params[:dup_giver] + ChallengeAssignment.duplicate_givers(@collection).order_by_offering_pseud + elsif params[:dup_recipient] + ChallengeAssignment.duplicate_recipients(@collection).order_by_requesting_pseud + else + @collection.assignments.with_request.with_offer.order_by_requesting_pseud + end @assignments = @assignments.paginate page: params[:page], per_page: ArchiveConfig.ITEMS_PER_PAGE end end @@ -100,13 +115,13 @@ def index # Generate potential matches def generate if PotentialMatch.in_progress?(@collection) - flash[:error] = ts("Potential matches are already being generated for this collection!") + flash[:error] = t("potential_matches.generate.already_in_progress") else # delete all existing assignments and potential matches for this collection ChallengeAssignment.clear!(@collection) PotentialMatch.clear!(@collection) - flash[:notice] = ts("Beginning generation of potential matches. This may take some time, especially if your challenge is large.") + flash[:notice] = t("potential_matches.generate.started") PotentialMatch.set_up_generating(@collection) PotentialMatch.generate(@collection) end @@ -118,11 +133,10 @@ def generate # Regenerate matches for one signup def regenerate_for_signup if params[:signup_id].blank? || (@signup = ChallengeSignup.where(id: params[:signup_id]).first).nil? - flash[:error] = ts("What sign-up did you want to regenerate matches for?") + flash[:error] = t("potential_matches.regenerate_for_signup.no_signup") else PotentialMatch.regenerate_for_signup(@signup) - flash[:notice] = ts("Matches are being regenerated for ") + @signup.pseud.byline + - ts(". Please allow at least 5 minutes for this process to complete before refreshing the page.") + flash[:notice] = t("potential_matches.regenerate_for_signup.started", pseud: @signup.pseud.byline) end # redirect to index redirect_to collection_potential_matches_path(@collection) @@ -130,12 +144,12 @@ def regenerate_for_signup def cancel_generate if !PotentialMatch.in_progress?(@collection) - flash[:error] = ts("Potential matches are not currently being generated for this challenge.") + flash[:error] = t("potential_matches.cancel_generate.not_in_progress") elsif PotentialMatch.canceled?(@collection) - flash[:error] = ts("Potential match generation has already been canceled, please refresh again shortly.") + flash[:error] = t("potential_matches.cancel_generate.already_canceled") else PotentialMatch.cancel_generation(@collection) - flash[:notice] = ts("Potential match generation cancellation requested. This may take a while, please refresh shortly.") + flash[:notice] = t("potential_matches.cancel_generate.requested") end redirect_to collection_potential_matches_path(@collection) diff --git a/config/locales/controllers/en.yml b/config/locales/controllers/en.yml index d81ec0b1029..6206462822a 100644 --- a/config/locales/controllers/en.yml +++ b/config/locales/controllers/en.yml @@ -95,9 +95,77 @@ en: access_denied_user: You aren't allowed to see that user's assignments. validation: not_owner: You aren't the owner of that assignment. + challenge_claims: + no_challenge: What challenge did you want to work with? + no_claim: What claim did you want to work on? + no_user: What user were you trying to work with? + owner_only: You aren't the claimer of that prompt. + index: + challenge_closed: This challenge is currently closed to new posts. + access_denied_user_claims: You aren't allowed to see that user's claims. + destroy: + claim_deleted: The claim was deleted. + your_claim_deleted: Your claim was deleted. + delete_failed: We couldn't delete that right now, sorry! Please try again later. + challenge_requests: + check_visibility: + collection_not_found: Collection could not be found + access_denied: You are not allowed to view the requests summary! challenge_signups: + no_challenge: What challenge did you want to sign up for? + signup_closed: Sign-up is currently closed: please contact a moderator for help. + not_signup_owner: You can't edit someone else's sign-up! + check_pseud_ownership: + invalid_pseud: You can't sign up with that pseud. + check_signup_in_collection: + signup_not_in_collection: Sorry, that sign-up isn't associated with that collection. + index: + access_denied_user_signups: You aren't allowed to see that user's sign-ups. + access_denied_csv: You aren't allowed to see the CSV summary. + summary: + minimum_signups: Summary does not appear until at least %{count} sign-ups have been made! + show: + invalid_signup: This sign-up is invalid. Please check your sign-ups for a duplicate or edit to fix any other problems. + build_prompts: + must_submit_at_least: You must submit at least %{required} %{prompt_type}. + can_only_submit_up_to: You can only submit up to %{allowed} %{prompt_type}. + set_up_num: Set up %{num} %{prompt_type}. + request_to_array: + any_type: Any %{type} new: page_title: New Challenge Sign-up + already_signed_up: You are already signed up for this challenge. You can edit your sign-up below. + create: + success: Sign-up was successfully created. + update: + success: Sign-up was successfully updated. + destroy: + success: Challenge sign-up was deleted. + signups_closed: You cannot delete your sign-up after sign-ups are closed. Please contact a moderator for help. + challenge: + gift_exchange: + already_set_up: There is already a challenge set up for this collection. + create: + success: Challenge was successfully created. + update: + success: Challenge was successfully updated. + potential_matches: + no_challenge: What challenge did you want to sign up for? + no_assignment: What potential match did you want to work on? + signup_open: Sign-up is still open, you cannot determine potential matches now. + assignments_sent: Assignments have already been sent! If necessary, you can purge them. + index: + matching_error: There has been an error in the potential matching. Please first try regenerating assignments, and if that doesn't work, all potential matches. If the problem persists, please contact Support. + generate: + already_in_progress: Potential matches are already being generated for this collection! + started: Beginning generation of potential matches. This may take some time, especially if your challenge is large. + regenerate_for_signup: + no_signup: What sign-up did you want to regenerate matches for? + started: "Matches are being regenerated for %{pseud}. Please allow at least 5 minutes for this process to complete before refreshing the page." + cancel_generate: + not_in_progress: Potential matches are not currently being generated for this challenge. + already_canceled: Potential match generation has already been canceled, please refresh again shortly. + requested: Potential match generation cancellation requested. This may take a while, please refresh shortly. chapters: destroy: only_chapter: You can't delete the only chapter in your work. If you want to delete the work, choose "Delete Work". From 1aae43dea322cdc3e66918146e5ef22603103cca Mon Sep 17 00:00:00 2001 From: not-varram Date: Tue, 17 Feb 2026 20:43:26 -0800 Subject: [PATCH 4/5] fix #3 --- config/locales/controllers/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/controllers/en.yml b/config/locales/controllers/en.yml index 6206462822a..0f651066225 100644 --- a/config/locales/controllers/en.yml +++ b/config/locales/controllers/en.yml @@ -113,7 +113,7 @@ en: access_denied: You are not allowed to view the requests summary! challenge_signups: no_challenge: What challenge did you want to sign up for? - signup_closed: Sign-up is currently closed: please contact a moderator for help. + signup_closed: "Sign-up is currently closed: please contact a moderator for help." not_signup_owner: You can't edit someone else's sign-up! check_pseud_ownership: invalid_pseud: You can't sign up with that pseud. From e408677c759c108b406a072f5bf7ec77132a4397 Mon Sep 17 00:00:00 2001 From: not-varram Date: Tue, 17 Feb 2026 21:01:30 -0800 Subject: [PATCH 5/5] try 4 --- config/locales/controllers/en.yml | 104 +++++++++++++++--------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/config/locales/controllers/en.yml b/config/locales/controllers/en.yml index 0f651066225..a4b4e219ea0 100644 --- a/config/locales/controllers/en.yml +++ b/config/locales/controllers/en.yml @@ -90,82 +90,65 @@ en: success: Bookmark was successfully created. It should appear in bookmark listings within the next few minutes. warnings: private_bookmark_added_to_collection: " Please note: private bookmarks are not listed in collections." + challenge: + gift_exchange: + already_set_up: There is already a challenge set up for this collection. + create: + success: Challenge was successfully created. + update: + success: Challenge was successfully updated. challenge_assignments: index: access_denied_user: You aren't allowed to see that user's assignments. validation: not_owner: You aren't the owner of that assignment. challenge_claims: + destroy: + claim_deleted: The claim was deleted. + delete_failed: We couldn't delete that right now, sorry! Please try again later. + your_claim_deleted: Your claim was deleted. + index: + access_denied_user_claims: You aren't allowed to see that user's claims. + challenge_closed: This challenge is currently closed to new posts. no_challenge: What challenge did you want to work with? no_claim: What claim did you want to work on? no_user: What user were you trying to work with? owner_only: You aren't the claimer of that prompt. - index: - challenge_closed: This challenge is currently closed to new posts. - access_denied_user_claims: You aren't allowed to see that user's claims. - destroy: - claim_deleted: The claim was deleted. - your_claim_deleted: Your claim was deleted. - delete_failed: We couldn't delete that right now, sorry! Please try again later. challenge_requests: check_visibility: - collection_not_found: Collection could not be found access_denied: You are not allowed to view the requests summary! + collection_not_found: Collection could not be found challenge_signups: - no_challenge: What challenge did you want to sign up for? - signup_closed: "Sign-up is currently closed: please contact a moderator for help." - not_signup_owner: You can't edit someone else's sign-up! + build_prompts: + can_only_submit_up_to: You can only submit up to %{allowed} %{prompt_type}. + must_submit_at_least: You must submit at least %{required} %{prompt_type}. + set_up_num: Set up %{num} %{prompt_type}. check_pseud_ownership: invalid_pseud: You can't sign up with that pseud. check_signup_in_collection: signup_not_in_collection: Sorry, that sign-up isn't associated with that collection. + create: + success: Sign-up was successfully created. + destroy: + signups_closed: You cannot delete your sign-up after sign-ups are closed. Please contact a moderator for help. + success: Challenge sign-up was deleted. index: - access_denied_user_signups: You aren't allowed to see that user's sign-ups. access_denied_csv: You aren't allowed to see the CSV summary. - summary: - minimum_signups: Summary does not appear until at least %{count} sign-ups have been made! - show: - invalid_signup: This sign-up is invalid. Please check your sign-ups for a duplicate or edit to fix any other problems. - build_prompts: - must_submit_at_least: You must submit at least %{required} %{prompt_type}. - can_only_submit_up_to: You can only submit up to %{allowed} %{prompt_type}. - set_up_num: Set up %{num} %{prompt_type}. - request_to_array: - any_type: Any %{type} + access_denied_user_signups: You aren't allowed to see that user's sign-ups. new: - page_title: New Challenge Sign-up already_signed_up: You are already signed up for this challenge. You can edit your sign-up below. - create: - success: Sign-up was successfully created. + page_title: New Challenge Sign-up + no_challenge: What challenge did you want to sign up for? + not_signup_owner: You can't edit someone else's sign-up! + request_to_array: + any_type: Any %{type} + show: + invalid_signup: This sign-up is invalid. Please check your sign-ups for a duplicate or edit to fix any other problems. + signup_closed: 'Sign-up is currently closed: please contact a moderator for help.' + summary: + minimum_signups: Summary does not appear until at least %{count} sign-ups have been made! update: success: Sign-up was successfully updated. - destroy: - success: Challenge sign-up was deleted. - signups_closed: You cannot delete your sign-up after sign-ups are closed. Please contact a moderator for help. - challenge: - gift_exchange: - already_set_up: There is already a challenge set up for this collection. - create: - success: Challenge was successfully created. - update: - success: Challenge was successfully updated. - potential_matches: - no_challenge: What challenge did you want to sign up for? - no_assignment: What potential match did you want to work on? - signup_open: Sign-up is still open, you cannot determine potential matches now. - assignments_sent: Assignments have already been sent! If necessary, you can purge them. - index: - matching_error: There has been an error in the potential matching. Please first try regenerating assignments, and if that doesn't work, all potential matches. If the problem persists, please contact Support. - generate: - already_in_progress: Potential matches are already being generated for this collection! - started: Beginning generation of potential matches. This may take some time, especially if your challenge is large. - regenerate_for_signup: - no_signup: What sign-up did you want to regenerate matches for? - started: "Matches are being regenerated for %{pseud}. Please allow at least 5 minutes for this process to complete before refreshing the page." - cancel_generate: - not_in_progress: Potential matches are not currently being generated for this challenge. - already_canceled: Potential match generation has already been canceled, please refresh again shortly. - requested: Potential match generation cancellation requested. This may take a while, please refresh shortly. chapters: destroy: only_chapter: You can't delete the only chapter in your work. If you want to delete the work, choose "Delete Work". @@ -303,6 +286,23 @@ en: people: index: collection_page_title: "%{collection_title} - People" + potential_matches: + assignments_sent: Assignments have already been sent! If necessary, you can purge them. + cancel_generate: + already_canceled: Potential match generation has already been canceled, please refresh again shortly. + not_in_progress: Potential matches are not currently being generated for this challenge. + requested: Potential match generation cancellation requested. This may take a while, please refresh shortly. + generate: + already_in_progress: Potential matches are already being generated for this collection! + started: Beginning generation of potential matches. This may take some time, especially if your challenge is large. + index: + matching_error: There has been an error in the potential matching. Please first try regenerating assignments, and if that doesn't work, all potential matches. If the problem persists, please contact Support. + no_assignment: What potential match did you want to work on? + no_challenge: What challenge did you want to sign up for? + regenerate_for_signup: + no_signup: What sign-up did you want to regenerate matches for? + started: Matches are being regenerated for %{pseud}. Please allow at least 5 minutes for this process to complete before refreshing the page. + signup_open: Sign-up is still open, you cannot determine potential matches now. preferences: update: error: Sorry, something went wrong. Please try that again.