From 324b4a83245dfaa6c3b72761ec96f3b81395f8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Wed, 3 Apr 2024 18:50:53 +0200 Subject: [PATCH 1/3] add views --- .github/workflows/lint.yml | 4 +- .simplecov | 1 + Gemfile.lock | 8 ++++ README.md | 2 +- app/models/decidim/anonymous_codes/group.rb | 5 ++ .../add_linked_group.html.erb.deface | 5 ++ .../_callout.html.erb | 18 +++++++ config/locales/en.yml | 15 ++++++ ...6_create_decidim_anonymous_codes_groups.rb | 2 + db/seeds.rb | 33 +++++++++++++ decidim-anonymous_codes.gemspec | 1 + lib/decidim/anonymous_codes/engine.rb | 2 + lib/decidim/anonymous_codes/test/factories.rb | 3 +- spec/factories.rb | 1 + spec/models/group_spec.rb | 5 ++ .../admin/surveys_component_settings_spec.rb | 47 +++++++++++++++++++ 16 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 app/overrides/decidim/admin/components/_settings_fields/add_linked_group.html.erb.deface create mode 100644 app/views/decidim/anonymous_codes/admin/surveys_component_settings/_callout.html.erb create mode 100644 db/seeds.rb create mode 100644 spec/system/admin/surveys_component_settings_spec.rb diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c5e6cf7..6b80149 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -40,5 +40,5 @@ jobs: - run: bundle exec rubocop -P name: Lint Ruby files - # - run: bundle exec erblint app/**/*.erb - # name: Lint ERB files + - run: bundle exec erblint app/**/*.erb + name: Lint ERB files diff --git a/.simplecov b/.simplecov index 7a815ae..7da6434 100644 --- a/.simplecov +++ b/.simplecov @@ -4,6 +4,7 @@ SimpleCov.start do root ENV.fetch("ENGINE_ROOT", nil) add_filter "lib/decidim/anonymous_codes/version.rb" + add_filter "lib/decidim/anonymous_codes/test" add_filter "/spec" end diff --git a/Gemfile.lock b/Gemfile.lock index 69533f5..2571c53 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,6 +5,7 @@ PATH decidim-admin (>= 0.27.0, < 0.28) decidim-core (>= 0.27.0, < 0.28) decidim-surveys (>= 0.27.0, < 0.28) + deface (>= 1.9.0) GEM remote: https://rubygems.org/ @@ -331,6 +332,12 @@ GEM declarative-builder (0.1.0) declarative-option (< 0.2.0) declarative-option (0.1.0) + deface (1.9.0) + actionview (>= 5.2) + nokogiri (>= 1.6) + polyglot + railties (>= 5.2) + rainbow (>= 2.1.0) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) devise (4.9.3) @@ -564,6 +571,7 @@ GEM pg_search (2.3.6) activerecord (>= 5.2) activesupport (>= 5.2) + polyglot (0.3.5) premailer (1.21.0) addressable css_parser (>= 1.12.0) diff --git a/README.md b/README.md index d005046..f3c4235 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Decidim::AnonymousCodes.configure do |config| # The generator to use for the codes (defaults to an alphanumeric uppercase string of length "default_token_length") # if you customize this, the default_token_length will be ignored def self.token_generator - SecureRandom.hex(25) + SecureRandom.hex(25) end end ``` diff --git a/app/models/decidim/anonymous_codes/group.rb b/app/models/decidim/anonymous_codes/group.rb index 5c7574b..202f3e0 100644 --- a/app/models/decidim/anonymous_codes/group.rb +++ b/app/models/decidim/anonymous_codes/group.rb @@ -10,8 +10,13 @@ class Group < ApplicationRecord throw(:abort) if tokens.where(usage_count: 1..Float::INFINITY).count.positive? end + belongs_to :organization, class_name: "Decidim::Organization", foreign_key: "decidim_organization_id" has_many :tokens, class_name: "Decidim::AnonymousCodes::Token", dependent: :destroy belongs_to :resource, polymorphic: true, optional: true + + def self.for(organization) + where(organization: organization) + end end end end diff --git a/app/overrides/decidim/admin/components/_settings_fields/add_linked_group.html.erb.deface b/app/overrides/decidim/admin/components/_settings_fields/add_linked_group.html.erb.deface new file mode 100644 index 0000000..f1028e7 --- /dev/null +++ b/app/overrides/decidim/admin/components/_settings_fields/add_linked_group.html.erb.deface @@ -0,0 +1,5 @@ + + +<% if manifest.name == :surveys && field_name == :allow_unregistered %> + <%= render "decidim/anonymous_codes/admin/surveys_component_settings/callout", resource: Decidim::Surveys::Survey.find_by(component: @component) %> +<% end %> diff --git a/app/views/decidim/anonymous_codes/admin/surveys_component_settings/_callout.html.erb b/app/views/decidim/anonymous_codes/admin/surveys_component_settings/_callout.html.erb new file mode 100644 index 0000000..11ff6e6 --- /dev/null +++ b/app/views/decidim/anonymous_codes/admin/surveys_component_settings/_callout.html.erb @@ -0,0 +1,18 @@ +<% groups = Decidim::AnonymousCodes::Group.for(@component.organization).where(resource: resource) %> +<% if groups.any? %> +
+

<%= t(".group_locked") %>

+ +

<%= t(".group_locked_desc") %>

+
+<% else %> +
+

<%= t(".group_unlocked") %>

+

<%= link_to t(".new_group"), "#" %>

+

<%= t(".group_unlocked_desc") %>

+
+<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 1491caf..ecc9f75 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,2 +1,17 @@ --- en: + decidim: + anonymous_codes: + admin: + surveys_component_settings: + callout: + group_locked: This survey can only be answered by using a valid code. + group_locked_desc: Note that, unless "Allow unregistered users to answer" + is enabled, only registered users can answer this survey (and they also + will have to provide the code). + group_unlocked: Anyone can answer this survey, but you can choose to restrict + this by using a answer codes. + group_unlocked_desc: Note that "Allow unregistered users to answer" will + still apply if you choose to use this option. + groups: 'Edit groups:' + new_group: "\U0001F449 Create answer codes here" diff --git a/db/migrate/20240403091336_create_decidim_anonymous_codes_groups.rb b/db/migrate/20240403091336_create_decidim_anonymous_codes_groups.rb index 57c17cb..e4c4ef0 100644 --- a/db/migrate/20240403091336_create_decidim_anonymous_codes_groups.rb +++ b/db/migrate/20240403091336_create_decidim_anonymous_codes_groups.rb @@ -9,6 +9,8 @@ def change t.boolean :active, default: true, null: false t.integer :max_reuses, default: 1, null: false t.references :resource, polymorphic: true, null: true, index: { name: "decidim_anonymous_codes_groups_on_resource" } + t.references :decidim_organization, null: false, foreign_key: true, index: { name: "decidim_anonymous_codes_groups_on_organization" } + t.timestamps end end diff --git a/db/seeds.rb b/db/seeds.rb new file mode 100644 index 0000000..0bc7ce5 --- /dev/null +++ b/db/seeds.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +if !Rails.env.production? || ENV.fetch("SEED", nil) + print "Creating seeds for decidim_anonymous_codes...\n" unless Rails.env.test? + + organization = Decidim::Organization.first + + group1 = Decidim::AnonymousCodes::Group.create!( + title: { en: "First Group" }, + organization: organization, + expires_at: 1.week.from_now, + active: true, + max_reuses: 1, + resource: Decidim::Surveys::Survey.first + ) + + group2 = Decidim::AnonymousCodes::Group.create!( + title: { en: "Second Group" }, + organization: organization, + expires_at: 1.week.from_now, + active: true, + max_reuses: 1, + resource: Decidim::Surveys::Survey.second + ) + + 5.times do + Decidim::AnonymousCodes::Token.create!(token: Decidim::AnonymousCodes.token_generator, usage_count: 0, group: group1) + end + + 25.times do + Decidim::AnonymousCodes::Token.create!(token: Decidim::AnonymousCodes.token_generator, usage_count: 0, group: group2) + end +end diff --git a/decidim-anonymous_codes.gemspec b/decidim-anonymous_codes.gemspec index 5bd6fec..78a68ae 100644 --- a/decidim-anonymous_codes.gemspec +++ b/decidim-anonymous_codes.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |spec| spec.add_dependency "decidim-admin", Decidim::AnonymousCodes::COMPAT_DECIDIM_VERSION spec.add_dependency "decidim-core", Decidim::AnonymousCodes::COMPAT_DECIDIM_VERSION spec.add_dependency "decidim-surveys", Decidim::AnonymousCodes::COMPAT_DECIDIM_VERSION + spec.add_dependency "deface", ">= 1.9.0" spec.add_development_dependency "decidim-dev", Decidim::AnonymousCodes::COMPAT_DECIDIM_VERSION spec.metadata["rubygems_mfa_required"] = "true" diff --git a/lib/decidim/anonymous_codes/engine.rb b/lib/decidim/anonymous_codes/engine.rb index b6ae4c4..c37b7d2 100644 --- a/lib/decidim/anonymous_codes/engine.rb +++ b/lib/decidim/anonymous_codes/engine.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "deface" + module Decidim module AnonymousCodes # This is the engine that runs on the public interface of decidim-anonymous_codes. diff --git a/lib/decidim/anonymous_codes/test/factories.rb b/lib/decidim/anonymous_codes/test/factories.rb index 307f441..8cc9a03 100644 --- a/lib/decidim/anonymous_codes/test/factories.rb +++ b/lib/decidim/anonymous_codes/test/factories.rb @@ -3,6 +3,7 @@ FactoryBot.define do factory :anonymous_codes_group, class: "Decidim::AnonymousCodes::Group" do title { { en: "Group title" } } + organization { create(:organization) } expires_at { 1.week.from_now } active { true } max_reuses { 1 } @@ -10,7 +11,7 @@ end factory :anonymous_codes_token, class: "Decidim::AnonymousCodes::Token" do - token { SecureRandom.uuid } + token { Decidim::AnonymousCodes.token_generator } usage_count { 0 } group { create(:anonymous_codes_group) } end diff --git a/spec/factories.rb b/spec/factories.rb index 089310e..ebe4f82 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -2,4 +2,5 @@ require "decidim/core/test/factories" require "decidim/surveys/test/factories" +require "decidim/proposals/test/factories" require "decidim/anonymous_codes/test/factories" diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 89665c0..136ef92 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -11,11 +11,16 @@ module AnonymousCodes describe "associations" do it { expect(described_class.reflect_on_association(:tokens).macro).to eq(:has_many) } + it { expect(described_class.reflect_on_association(:organization).macro).to eq(:belongs_to) } end context "when tokens exist" do let!(:token) { create(:anonymous_codes_token, group: group) } + it "has an organization" do + expect(group.organization).to be_a(Decidim::Organization) + end + it "destroys the tokens when destroyed" do expect { group.destroy }.to change(Token, :count).by(-1) end diff --git a/spec/system/admin/surveys_component_settings_spec.rb b/spec/system/admin/surveys_component_settings_spec.rb new file mode 100644 index 0000000..9e981bd --- /dev/null +++ b/spec/system/admin/surveys_component_settings_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe "Surveys Component Settings", type: :system do + let(:organization) { component.organization } + let(:component) { survey.component } + let(:user) { create :user, :admin, :confirmed, organization: organization } + let(:group) { create :anonymous_codes_group, organization: organization, resource: resource } + let!(:token) { create :anonymous_codes_token, group: group } + let!(:survey) { create(:survey) } + let(:resource) { nil } + + def visit_component + visit Decidim::EngineRouter.admin_proxy(component.participatory_space).edit_component_path(component.id) + end + + before do + switch_to_host(organization.host) + login_as user, scope: :user + visit_component + end + + it "has callout" do + within ".callout.warning" do + expect(page).to have_content("Create answer codes here") + end + end + + context "when codes are available" do + let(:resource) { survey } + + it "has callout" do + within ".callout.alert" do + expect(page).to have_content("This survey can only be answered by using a valid code") + end + end + end + + context "when not a surveys component" do + let(:component) { create :proposal_component } + + it "has no callout" do + expect(page).not_to have_css(".callout") + end + end +end From d04a51f131d80cdb02b8747d63b8032b6b3a6057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Wed, 3 Apr 2024 18:56:06 +0200 Subject: [PATCH 2/3] remove google chrome --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 25e522a..2dd5064 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,6 +38,9 @@ jobs: with: chromedriver-version: 119.0.6045.105 + - name: Remove Chrome + run: sudo apt remove google-chrome-stable + - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ env.RUBY_VERSION }} From 5eadb61461d270f7f3744e8778a70f91aaf595e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Wed, 3 Apr 2024 19:05:00 +0200 Subject: [PATCH 3/3] remove google chrome --- .github/workflows/test.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2dd5064..fcdf08a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,9 +38,18 @@ jobs: with: chromedriver-version: 119.0.6045.105 + - name: List Chrome + shell: "bash" + run: apt list --installed | grep chrome + - name: Remove Chrome + shell: "bash" run: sudo apt remove google-chrome-stable + - uses: browser-actions/setup-chrome@v1 + with: + chrome-version: 119.0.6045.105 + - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ env.RUBY_VERSION }}