diff --git a/app/components/users/public_activity_component.rb b/app/components/users/public_activity_component.rb
index 4c11f6069..8cdaa895c 100644
--- a/app/components/users/public_activity_component.rb
+++ b/app/components/users/public_activity_component.rb
@@ -1,6 +1,6 @@
class Users::PublicActivityComponent < ApplicationComponent
attr_reader :user
- delegate :authorized_current_user?, :current_path_with_query_params, to: :helpers
+ delegate :current_user, :valid_interests_access?, :current_path_with_query_params, to: :helpers
def initialize(user)
@user = user
@@ -24,12 +24,16 @@ class Users::PublicActivityComponent < ApplicationComponent
("debates" if feature?(:debates)),
("budget_investments" if feature?(:budgets)),
"comments",
- "follows"
+ ("follows" if valid_interests_access?(user))
].compact.select { |filter| send(filter).any? }
end
private
+ def authorized_current_user?
+ current_user == user || current_user&.moderator? || current_user&.administrator?
+ end
+
def proposals
Proposal.where(author_id: user.id)
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 0912f3295..8ccee9692 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1,18 +1,14 @@
class UsersController < ApplicationController
load_and_authorize_resource
helper_method :valid_interests_access?
- helper_method :authorized_current_user?
def show
+ raise CanCan::AccessDenied if params[:filter] == "follows" && !valid_interests_access?(@user)
end
private
- def valid_interests_access?
- @user.public_interests || authorized_current_user?
- end
-
- def authorized_current_user?
- @authorized_current_user ||= current_user && (current_user == @user || current_user.moderator? || current_user.administrator?)
+ def valid_interests_access?(user)
+ user.public_interests || user == current_user
end
end
diff --git a/app/views/users/_following.html.erb b/app/views/users/_following.html.erb
index 480bb2da2..d09f99fe6 100644
--- a/app/views/users/_following.html.erb
+++ b/app/views/users/_following.html.erb
@@ -22,6 +22,6 @@
- <%= render "interests", user: user if valid_interests_access? %>
+ <%= render "interests", user: user %>
diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml
index c2057e07b..2613671b5 100644
--- a/config/locales/en/activerecord.yml
+++ b/config/locales/en/activerecord.yml
@@ -281,7 +281,7 @@ en:
official_level: "Official level"
phone_number: "Phone number"
public_activity: "Keep my list of activities public"
- public_interests: "Keep the labels of the elements I follow public"
+ public_interests: "Keep the elements I follow public"
recommended_debates: "Show debates recommendations"
recommended_proposals: "Show proposals recommendations"
redeemable_code: "Verification code received via email"
diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml
index a6454e6e3..8af18867c 100644
--- a/config/locales/es/activerecord.yml
+++ b/config/locales/es/activerecord.yml
@@ -281,7 +281,7 @@ es:
official_level: "Nivel del cargo"
phone_number: "Teléfono"
public_activity: "Mostrar públicamente mi lista de actividades"
- public_interests: "Mostrar públicamente las etiquetas de los elementos que sigo"
+ public_interests: "Mostrar públicamente los elementos que sigo"
recommended_debates: "Mostrar recomendaciones en el listado de debates"
recommended_proposals: "Mostrar recomendaciones en el listado de propuestas"
redeemable_code: "Código de verificación por carta (opcional)"
diff --git a/spec/components/users/public_activity_component_spec.rb b/spec/components/users/public_activity_component_spec.rb
new file mode 100644
index 000000000..39ae4010d
--- /dev/null
+++ b/spec/components/users/public_activity_component_spec.rb
@@ -0,0 +1,82 @@
+require "rails_helper"
+
+describe Users::PublicActivityComponent, controller: UsersController do
+ around do |example|
+ with_request_url(Rails.application.routes.url_helpers.user_path(user)) { example.run }
+ end
+
+ describe "follows tab" do
+ context "public interests is checked" do
+ let(:user) { create(:user, public_interests: true) }
+ let(:component) { Users::PublicActivityComponent.new(user) }
+
+ it "is displayed for everyone" do
+ create(:proposal, author: user, followers: [user])
+
+ render_inline component
+
+ expect(page).to have_content "1 Following"
+ end
+
+ it "is not displayed when the user isn't following any followables" do
+ create(:proposal, author: user)
+
+ render_inline component
+
+ expect(page).not_to have_content "Following"
+ end
+
+ it "is the active tab when the follows filters is selected" do
+ create(:proposal, author: user, followers: [user])
+ controller.params["filter"] = "follows"
+
+ render_inline component
+
+ expect(page).to have_selector "li.is-active", text: "1 Following"
+ end
+ end
+
+ context "public interests is not checked" do
+ let(:user) { create(:user, public_interests: false) }
+ let(:component) { Users::PublicActivityComponent.new(user) }
+
+ it "is displayed for its owner" do
+ create(:proposal, followers: [user])
+ sign_in(user)
+
+ render_inline component
+
+ expect(page).to have_content "1 Following"
+ end
+
+ it "is not displayed for anonymous users" do
+ create(:proposal, author: user, followers: [user])
+
+ render_inline component
+
+ expect(page).to have_content "1 Proposal"
+ expect(page).not_to have_content "Following"
+ end
+
+ it "is not displayed for other users" do
+ create(:proposal, author: user, followers: [user])
+ sign_in(create(:user))
+
+ render_inline component
+
+ expect(page).to have_content "1 Proposal"
+ expect(page).not_to have_content "Following"
+ end
+
+ it "is not displayed for administrators" do
+ create(:proposal, author: user, followers: [user])
+ sign_in(create(:administrator).user)
+
+ render_inline component
+
+ expect(page).to have_content "1 Proposal"
+ expect(page).not_to have_content "Following"
+ end
+ end
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 3c6103c44..d24392549 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -739,6 +739,12 @@ describe User do
end
end
+ describe "#public_interests" do
+ it "is false by default" do
+ expect(User.new.public_interests).to be false
+ end
+ end
+
describe ".find_by_manager_login" do
it "works with a low ID" do
user = create(:user)
diff --git a/spec/system/users_spec.rb b/spec/system/users_spec.rb
index 5a9607f9c..127bb1b11 100644
--- a/spec/system/users_spec.rb
+++ b/spec/system/users_spec.rb
@@ -231,106 +231,6 @@ describe "Users" do
end
end
- describe "Public interests" do
- let(:user) { create(:user) }
-
- scenario "Display interests" do
- create(:proposal, tag_list: "Sport", followers: [user])
-
- login_as(user)
- visit account_path
-
- check "account_public_interests"
- click_button "Save changes"
-
- logout
-
- visit user_path(user, filter: "follows")
-
- expect(page).to have_css "#public_interests"
- expect(page).to have_content "Sport"
- end
-
- scenario "Not display interests when proposal has been destroyed" do
- proposal = create(:proposal, tag_list: "Sport", followers: [user])
- proposal.destroy!
-
- login_as(user)
- visit account_path
-
- check "account_public_interests"
- click_button "Save changes"
-
- logout
-
- visit user_path(user)
- expect(page).not_to have_content("Sport")
- end
-
- scenario "No visible by default" do
- visit user_path(user)
-
- expect(page).to have_content(user.username)
- expect(page).not_to have_css("#public_interests")
- end
-
- scenario "Is always visible for the owner" do
- create(:proposal, tag_list: "Sport", followers: [user])
-
- login_as(user)
- visit account_path
-
- uncheck "account_public_interests"
- click_button "Save changes"
-
- visit user_path(user, filter: "follows", page: "1")
-
- expect(page).to have_css "#public_interests"
- expect(page).to have_content "Tags of elements you follow"
- end
-
- scenario "Is always visible for admins" do
- create(:proposal, tag_list: "Sport", followers: [user])
-
- login_as(user)
- visit account_path
-
- uncheck "account_public_interests"
- click_button "Save changes"
-
- logout
-
- login_as(create(:administrator).user)
- visit user_path(user, filter: "follows", page: "1")
- expect(page).to have_css("#public_interests")
- end
-
- scenario "Is always visible for moderators" do
- create(:proposal, tag_list: "Sport", followers: [user])
-
- login_as(user)
- visit account_path
-
- uncheck "account_public_interests"
- click_button "Save changes"
-
- logout
-
- login_as(create(:moderator).user)
- visit user_path(user, filter: "follows", page: "1")
- expect(page).to have_css("#public_interests")
- end
-
- scenario "Should display generic interests title" do
- create(:proposal, tag_list: "Sport", followers: [user])
-
- user.update!(public_interests: true)
- visit user_path(user, filter: "follows", page: "1")
-
- expect(page).to have_content("Tags of elements this user follows")
- end
- end
-
describe "Special comments" do
scenario "comments posted as moderator are not visible in user activity" do
moderator = create(:administrator).user
@@ -386,117 +286,203 @@ describe "Users" do
describe "Following (public page)" do
let(:user) { create(:user) }
- scenario "Do not display follows' tab when user is not following any followables" do
- visit user_path(user)
+ context "public interests is checked" do
+ let(:user) { create(:user, public_interests: true) }
- expect(page).not_to have_content("0 Following")
+ scenario "can be accessed by anyone" do
+ create(:proposal, followers: [user], title: "Others follow me")
+
+ visit user_path(user, filter: "follows")
+
+ expect(page).to have_content "1 Following"
+ expect(page).to have_content "Others follow me"
+ end
+
+ scenario "Gracefully handle followables that have been hidden" do
+ create(:proposal, followers: [user])
+ create(:proposal, followers: [user], &:hide)
+
+ visit user_path(user)
+
+ expect(page).to have_content("1 Following")
+ end
+
+ scenario "displays generic interests title" do
+ create(:proposal, tag_list: "Sport", followers: [user])
+
+ visit user_path(user, filter: "follows", page: "1")
+
+ expect(page).to have_content("Tags of elements this user follows")
+ end
+
+ describe "Proposals" do
+ scenario "Display following tab when user is following one proposal at least" do
+ create(:proposal, followers: [user])
+
+ visit user_path(user)
+
+ expect(page).to have_content("1 Following")
+ end
+
+ scenario "Display proposal tab when user is following one proposal at least" do
+ create(:proposal, followers: [user])
+
+ visit user_path(user, filter: "follows")
+
+ expect(page).to have_link("Citizen proposals", href: "#citizen_proposals")
+ end
+
+ scenario "Do not display proposals' tab when user is not following any proposal" do
+ visit user_path(user, filter: "follows")
+
+ expect(page).not_to have_link("Citizen proposals", href: "#citizen_proposals")
+ end
+
+ scenario "Display proposals with link to proposal" do
+ proposal = create(:proposal, author: user, followers: [user])
+
+ login_as user
+
+ visit user_path(user, filter: "follows")
+
+ expect(page).to have_link "Citizen proposals", href: "#citizen_proposals"
+ expect(page).to have_content proposal.title
+ end
+
+ scenario "Retired proposals do not have a link to the dashboard" do
+ proposal = create(:proposal, :retired, author: user)
+ login_as user
+
+ visit user_path(user)
+
+ expect(page).to have_content proposal.title
+ expect(page).not_to have_link "Dashboard"
+ expect(page).to have_content("Dashboard not available for retired proposals")
+ end
+
+ scenario "Published proposals have a link to the dashboard" do
+ proposal = create(:proposal, :published, author: user)
+ login_as user
+
+ visit user_path(user)
+
+ expect(page).to have_content proposal.title
+ expect(page).to have_link "Dashboard"
+ end
+ end
+
+ describe "Budget Investments" do
+ scenario "Display following tab when user is following one budget investment at least" do
+ create(:budget_investment, followers: [user])
+
+ visit user_path(user)
+
+ expect(page).to have_content("1 Following")
+ end
+
+ scenario "Display budget investment tab when user is following one budget investment at least" do
+ create(:budget_investment, followers: [user])
+
+ visit user_path(user, filter: "follows")
+
+ expect(page).to have_link("Investments", href: "#investments")
+ end
+
+ scenario "Do not display budget investment tab when user is not following any budget investment" do
+ visit user_path(user, filter: "follows")
+
+ expect(page).not_to have_link("Investments", href: "#investments")
+ end
+
+ scenario "Display budget investment with link to budget investment" do
+ budget_investment = create(:budget_investment, author: user, followers: [user])
+
+ visit user_path(user, filter: "follows")
+
+ expect(page).to have_link "Investments", href: "#investments"
+ expect(page).to have_link budget_investment.title
+ end
+ end
end
- scenario "Active following tab by default when follows filters selected" do
- create(:proposal, author: user, followers: [user])
+ context "public interests is not checked" do
+ let(:user) { create(:user, public_interests: false) }
+
+ scenario "can be accessed by its owner" do
+ create(:proposal, followers: [user], title: "Follow me!")
+
+ login_as(user)
+
+ visit user_path(user, filter: "follows")
+
+ expect(page).to have_content "1 Following"
+ expect(page).to have_content "Follow me!"
+ expect(page).to have_content "Tags of elements you follow"
+ end
+
+ scenario "cannot be accessed by anonymous users" do
+ create(:proposal, followers: [user])
+
+ visit user_path(user, filter: "follows")
+
+ expect(page).to have_content "You do not have permission to access this page"
+ expect(page).to have_current_path root_path
+ end
+
+ scenario "cannot be accessed by other users" do
+ create(:proposal, followers: [user])
+
+ login_as(create(:user))
+
+ visit user_path(user, filter: "follows")
+
+ expect(page).to have_content "You do not have permission to access this page"
+ expect(page).to have_current_path root_path
+ end
+
+ scenario "cannot be accessed by administrators" do
+ create(:proposal, followers: [user])
+
+ login_as(create(:administrator).user)
+
+ visit user_path(user, filter: "follows")
+
+ expect(page).to have_content "You do not have permission to access this page"
+ expect(page).to have_current_path root_path
+ end
+ end
+
+ scenario "Display interests" do
+ create(:proposal, tag_list: "Sport", followers: [user])
+
+ login_as(user)
+ visit account_path
+
+ check "account_public_interests"
+ click_button "Save changes"
+
+ logout
visit user_path(user, filter: "follows")
- expect(page).to have_selector(".activity li.is-active", text: "1 Following")
+ expect(page).to have_css "#public_interests"
+ expect(page).to have_content "Sport"
end
- scenario "Gracefully handle followables that have been hidden" do
- create(:proposal, followers: [user])
- create(:proposal, followers: [user], &:hide)
+ scenario "Do not display interests when proposal has been destroyed" do
+ proposal = create(:proposal, tag_list: "Sport", followers: [user])
+ proposal.destroy!
+
+ login_as(user)
+ visit account_path
+
+ check "account_public_interests"
+ click_button "Save changes"
+
+ logout
visit user_path(user)
-
- expect(page).to have_content("1 Following")
- end
-
- describe "Proposals" do
- scenario "Display following tab when user is following one proposal at least" do
- create(:proposal, followers: [user])
-
- visit user_path(user)
-
- expect(page).to have_content("1 Following")
- end
-
- scenario "Display proposal tab when user is following one proposal at least" do
- create(:proposal, followers: [user])
-
- visit user_path(user, filter: "follows")
-
- expect(page).to have_link("Citizen proposals", href: "#citizen_proposals")
- end
-
- scenario "Do not display proposals' tab when user is not following any proposal" do
- visit user_path(user, filter: "follows")
-
- expect(page).not_to have_link("Citizen proposals", href: "#citizen_proposals")
- end
-
- scenario "Display proposals with link to proposal" do
- proposal = create(:proposal, author: user, followers: [user])
-
- login_as user
-
- visit user_path(user, filter: "follows")
-
- expect(page).to have_link "Citizen proposals", href: "#citizen_proposals"
- expect(page).to have_content proposal.title
- end
-
- scenario "Retired proposals do not have a link to the dashboard" do
- proposal = create(:proposal, :retired, author: user)
- login_as user
-
- visit user_path(user)
-
- expect(page).to have_content proposal.title
- expect(page).not_to have_link "Dashboard"
- expect(page).to have_content("Dashboard not available for retired proposals")
- end
-
- scenario "Published proposals have a link to the dashboard" do
- proposal = create(:proposal, :published, author: user)
- login_as user
-
- visit user_path(user)
-
- expect(page).to have_content proposal.title
- expect(page).to have_link "Dashboard"
- end
- end
-
- describe "Budget Investments" do
- scenario "Display following tab when user is following one budget investment at least" do
- create(:budget_investment, followers: [user])
-
- visit user_path(user)
-
- expect(page).to have_content("1 Following")
- end
-
- scenario "Display budget investment tab when user is following one budget investment at least" do
- create(:budget_investment, followers: [user])
-
- visit user_path(user, filter: "follows")
-
- expect(page).to have_link("Investments", href: "#investments")
- end
-
- scenario "Not display budget investment tab when user is not following any budget investment" do
- visit user_path(user, filter: "follows")
-
- expect(page).not_to have_link("Investments", href: "#investments")
- end
-
- scenario "Display budget investment with link to budget investment" do
- user = create(:user, :level_two)
- budget_investment = create(:budget_investment, author: user, followers: [user])
-
- visit user_path(user, filter: "follows")
-
- expect(page).to have_link "Investments", href: "#investments"
- expect(page).to have_link budget_investment.title
- end
+ expect(page).not_to have_content("Sport")
end
end