decidim-department_admin 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +132 -0
  4. data/Rakefile +9 -0
  5. data/app/controllers/decidim/department_admin/admin/application_controller.rb +15 -0
  6. data/app/controllers/decidim/department_admin/application_controller.rb +13 -0
  7. data/app/decorators/decidim/admin/newsletters_controller_decorator.rb +30 -0
  8. data/app/decorators/decidim/admin/users_controller_decorator.rb +128 -0
  9. data/app/decorators/decidim/area_decorator.rb +44 -0
  10. data/app/decorators/decidim/assemblies/admin/assemblies_controller_decorator.rb +25 -0
  11. data/app/decorators/decidim/assemblies/admin/assemblies_helper_decorator.rb +24 -0
  12. data/app/decorators/decidim/assemblies/create_assembly_decorator.rb +19 -0
  13. data/app/decorators/decidim/assemblies/parent_assemblies_for_select_decorator.rb +38 -0
  14. data/app/decorators/decidim/assemblies/permissions_decorator.rb +22 -0
  15. data/app/decorators/decidim/assemblies/update_assembly_decorator.rb +19 -0
  16. data/app/decorators/decidim/assemblies_decorator.rb +21 -0
  17. data/app/decorators/decidim/assemblies_with_user_role_decorator.rb +27 -0
  18. data/app/decorators/decidim/conference_form_decorator.rb +23 -0
  19. data/app/decorators/decidim/conferences/admin/conferences_controller_decorator.rb +27 -0
  20. data/app/decorators/decidim/conferences/create_conference_decorator.rb +51 -0
  21. data/app/decorators/decidim/conferences/permissions_decorator.rb +24 -0
  22. data/app/decorators/decidim/conferences/update_conference_decorator.rb +21 -0
  23. data/app/decorators/decidim/conferences_decorator.rb +27 -0
  24. data/app/decorators/decidim/conferences_with_user_role_decorator.rb +29 -0
  25. data/app/decorators/decidim/decidim_form_helper_decorator.rb +23 -0
  26. data/app/decorators/decidim/invite_user_decorator.rb +56 -0
  27. data/app/decorators/decidim/invite_user_form_decorator.rb +45 -0
  28. data/app/decorators/decidim/newsletter_decorator.rb +20 -0
  29. data/app/decorators/decidim/newsletters_helper_decorator.rb +44 -0
  30. data/app/decorators/decidim/participatory_process_decorator.rb +21 -0
  31. data/app/decorators/decidim/participatory_process_group_decorator.rb +17 -0
  32. data/app/decorators/decidim/participatory_processes/admin/participatory_processes_controller_decorator.rb +25 -0
  33. data/app/decorators/decidim/participatory_processes/create_participatory_process_decorator.rb +19 -0
  34. data/app/decorators/decidim/participatory_processes/permissions_decorator.rb +22 -0
  35. data/app/decorators/decidim/participatory_processes/update_participatory_process_decorator.rb +19 -0
  36. data/app/decorators/decidim/participatory_processes_with_user_role_decorator.rb +27 -0
  37. data/app/decorators/decidim/user_decorator.rb +59 -0
  38. data/app/decorators/lib/decidim/participatory_space_resourceable_decorator.rb +36 -0
  39. data/app/helpers/decidim/admin/user_roles_helper.rb +25 -0
  40. data/app/helpers/decidim/department_admin/application_helper.rb +54 -0
  41. data/app/models/decidim/participatory_space_role_config/department_admin.rb +8 -0
  42. data/app/overrides/decidim/admin/shared/add_radio_buttons_to_filters.rb +6 -0
  43. data/app/packs/entrypoints/decidim_department_admin.js +4 -0
  44. data/app/packs/entrypoints/decidim_department_admin.scss +1 -0
  45. data/app/packs/images/decidim/department_admin/icon.svg +1 -0
  46. data/app/packs/stylesheets/decidim/admin/department_admin.scss +5 -0
  47. data/app/permissions/decidim/assemblies/participatory_space_permissions.rb +14 -0
  48. data/app/permissions/decidim/conferences/participatory_space_permissions.rb +17 -0
  49. data/app/permissions/decidim/department_admin/permissions.rb +240 -0
  50. data/app/permissions/decidim/participatory_processes/participatory_space_permissions.rb +14 -0
  51. data/app/queries/decidim/admin/user_admin_by_space_name_filter.rb +67 -0
  52. data/app/queries/decidim/admin/user_admin_filter.rb +50 -0
  53. data/app/views/decidim/admin/users/_filters.html.erb +28 -0
  54. data/app/views/decidim/admin/users/_form.html.erb +30 -0
  55. data/app/views/decidim/admin/users/index.html.erb +93 -0
  56. data/app/views/decidim/admin/users/show.html.erb +99 -0
  57. data/app/views/decidim/assemblies/admin/assemblies/index.html.erb +147 -0
  58. data/app/views/decidim/conferences/admin/conferences/_form.html.erb +127 -0
  59. data/app/views/decidim/conferences/admin/conferences/index.html.erb +85 -0
  60. data/app/views/decidim/participatory_processes/admin/participatory_processes/index.html.erb +160 -0
  61. data/config/assets.rb +27 -0
  62. data/config/i18n-tasks.yml +148 -0
  63. data/config/initializers/user_roles.rb +4 -0
  64. data/config/locales/ca.yml +61 -0
  65. data/config/locales/cs.yml +46 -0
  66. data/config/locales/en.yml +61 -0
  67. data/config/locales/es.yml +61 -0
  68. data/db/migrate/20190328130102_create_department_admin_areas.rb +10 -0
  69. data/db/migrate/20210420143021_add_area_to_conferences.rb +7 -0
  70. data/lib/decidim/department_admin/admin.rb +10 -0
  71. data/lib/decidim/department_admin/admin_engine.rb +27 -0
  72. data/lib/decidim/department_admin/engine.rb +137 -0
  73. data/lib/decidim/department_admin/test/factories.rb +17 -0
  74. data/lib/decidim/department_admin/version.rb +11 -0
  75. data/lib/decidim/department_admin.rb +15 -0
  76. data/spec/commands/decidim/admin/deliver_newsletter_spec.rb +175 -0
  77. data/spec/commands/decidim/invite_user_spec.rb +42 -0
  78. data/spec/controllers/decidim/admin/users_controller_spec.rb +119 -0
  79. data/spec/factories.rb +4 -0
  80. data/spec/features/check_overrides_spec.rb +11 -0
  81. data/spec/i18n_spec.rb +29 -0
  82. data/spec/models/decidim/area_spec.rb +23 -0
  83. data/spec/permissions/decidim/department_admin/department_admin_permissions_spec.rb +120 -0
  84. data/spec/queries/parent_assemblies_for_select_spec.rb +52 -0
  85. data/spec/spec_helper.rb +47 -0
  86. data/spec/system/admin_explores_processes_spec.rb +53 -0
  87. data/spec/system/admin_invite_department_admin_spec.rb +118 -0
  88. data/spec/system/department_admin_manages_newsletters_spec.rb +237 -0
  89. data/spec/system/department_admin_should_be_able_to_access_admin_dashboard_spec.rb +75 -0
  90. data/spec/system/department_admin_should_be_able_to_manage_assemblies_spec.rb +99 -0
  91. data/spec/system/department_admin_should_be_able_to_manage_conferences_spec.rb +74 -0
  92. data/spec/system/department_admin_should_be_able_to_manage_processes_spec.rb +117 -0
  93. data/spec/system/department_admin_should_be_able_to_see_only_assemblies_from_her_area_spec.rb +46 -0
  94. data/spec/system/department_admin_should_be_able_to_see_only_newsletters_from_her_area_spec.rb +53 -0
  95. data/spec/system/department_admin_should_be_able_to_see_only_processes_from_her_area_spec.rb +50 -0
  96. metadata +229 -0
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim::Admin
6
+ describe DeliverNewsletter do
7
+ describe "call" do
8
+ let(:organization) { create(:organization) }
9
+ let(:newsletter) do
10
+ create(:newsletter,
11
+ organization: organization,
12
+ author: current_user)
13
+ end
14
+ let(:area) { create(:area, organization: organization) }
15
+ let(:current_user) { create(:department_admin, :confirmed, organization: organization, area: area) }
16
+ let(:send_to_all_users) { false }
17
+ let(:send_to_followers) { false }
18
+ let(:send_to_participants) { false }
19
+ let(:participatory_space_types) { [] }
20
+ let(:scope_ids) { [] }
21
+
22
+ let(:form_params) do
23
+ {
24
+ send_to_all_users: send_to_all_users,
25
+ send_to_followers: send_to_followers,
26
+ send_to_participants: send_to_participants,
27
+ participatory_space_types: participatory_space_types,
28
+ scope_ids: scope_ids,
29
+ }
30
+ end
31
+
32
+ let(:form) do
33
+ SelectiveNewsletterForm.from_params(
34
+ form_params
35
+ ).with_context(
36
+ current_organization: organization,
37
+ current_user: current_user
38
+ )
39
+ end
40
+
41
+ let(:command) { described_class.new(newsletter, form, current_user) }
42
+
43
+ shared_examples_for "selective newsletter" do
44
+ context "when everything is ok" do
45
+ it "updates the counters and delivers to the right users" do
46
+ clear_emails
47
+ expect(emails.length).to eq(0)
48
+
49
+ perform_enqueued_jobs { command.call }
50
+
51
+ expect(emails.length).to eq(deliverable_users.count)
52
+
53
+ newsletter.reload
54
+ expect(newsletter.total_deliveries).to eq(deliverable_users.count)
55
+ expect(newsletter.total_recipients).to eq(deliverable_users.count)
56
+ end
57
+
58
+ it "logs the action", versioning: true do
59
+ expect(Decidim.traceability)
60
+ .to receive(:perform_action!)
61
+ .with("deliver", newsletter, current_user)
62
+ .and_call_original
63
+
64
+ expect do
65
+ perform_enqueued_jobs { command.call }
66
+ end.to change(Decidim::ActionLog, :count)
67
+
68
+ action_log = Decidim::ActionLog.last
69
+ expect(action_log.version).to be_present
70
+ expect(action_log.version.event).to eq "update"
71
+ end
72
+ end
73
+ end
74
+
75
+ context "when the user is a department admin" do
76
+ let!(:participatory_process) { create(:participatory_process, organization: organization, area: area) }
77
+ let!(:component) { create(:dummy_component, organization: newsletter.organization, participatory_space: participatory_process) }
78
+
79
+ context "when no spaces selected" do
80
+ it "is not valid" do
81
+ expect { command.call }.to broadcast(:invalid)
82
+ end
83
+ end
84
+
85
+ context "when spaces selected" do
86
+ let(:participatory_space_types) do
87
+ [
88
+ { "id" => nil,
89
+ "manifest_name" => "participatory_processes",
90
+ "ids" => [component.participatory_space.id.to_s] },
91
+ { "id" => nil,
92
+ "manifest_name" => "assemblies",
93
+ "ids" => [] },
94
+ { "id" => nil,
95
+ "manifest_name" => "conferences",
96
+ "ids" => [] },
97
+ { "id" => nil,
98
+ "manifest_name" => "consultations",
99
+ "ids" => [] },
100
+ { "id" => nil,
101
+ "manifest_name" => "initiatives",
102
+ "ids" => [] },
103
+ ]
104
+ end
105
+
106
+ context "when sending to followers" do
107
+ let(:send_to_followers) { true }
108
+
109
+ let!(:deliverable_users) do
110
+ create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current)
111
+ end
112
+
113
+ let!(:undeliverable_users) do
114
+ create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current)
115
+ end
116
+
117
+ before do
118
+ deliverable_users.each do |follower|
119
+ create(:follow, followable: participatory_process, user: follower)
120
+ end
121
+ end
122
+
123
+ it_behaves_like "selective newsletter"
124
+ end
125
+
126
+ context "when sending to all space participants" do
127
+ let(:send_to_participants) { true }
128
+ let!(:deliverable_users) do
129
+ create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current)
130
+ end
131
+
132
+ before do
133
+ deliverable_users.each do |participant|
134
+ create(:dummy_resource, component: component, author: participant, published_at: Time.current)
135
+ end
136
+ end
137
+
138
+ it_behaves_like "selective newsletter"
139
+ end
140
+
141
+ context "when sending to followers and participants" do
142
+ let(:send_to_participants) { true }
143
+ let(:send_to_followers) { true }
144
+
145
+ let!(:participant_users) do
146
+ create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current)
147
+ end
148
+
149
+ let!(:follower_users) do
150
+ create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current)
151
+ end
152
+
153
+ let!(:deliverable_users) { participant_users + follower_users }
154
+
155
+ let!(:undeliverable_users) do
156
+ create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current)
157
+ end
158
+
159
+ before do
160
+ participant_users.each do |participant|
161
+ create(:dummy_resource, component: component, author: participant, published_at: Time.current)
162
+ end
163
+
164
+ follower_users.each do |follower|
165
+ create(:follow, followable: component.participatory_space, user: follower)
166
+ end
167
+ end
168
+
169
+ it_behaves_like "selective newsletter"
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ describe InviteUser do
7
+ describe "call" do
8
+ let(:organization) { create(:organization) }
9
+
10
+ let(:current_user) { create(:admin, :confirmed, organization: organization) }
11
+
12
+ let(:form_params) do
13
+ {
14
+ name: "user_name",
15
+ email: "user_name@example.org",
16
+ organization: organization,
17
+ }
18
+ end
19
+
20
+ let(:form) do
21
+ InviteUserForm.from_params(
22
+ form_params
23
+ ).with_context(
24
+ current_organization: organization,
25
+ current_user: current_user
26
+ )
27
+ end
28
+
29
+ let(:command) { described_class.new(form, current_user) }
30
+
31
+ shared_examples_for "inviting_users" do
32
+ context "when everything is ok" do
33
+ it "invites the user with no area" do
34
+ invite_user
35
+ user = Decidim::User.find_by(email: "user_name@example.org")
36
+ expect(user).to exist
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim::Admin
6
+ describe UsersController, type: :controller do
7
+ # routes { Decidim::Core::Engine.routes }
8
+ routes { Decidim::Admin::Engine.routes }
9
+
10
+ let!(:admin_user) { create(:user, :admin, :confirmed) }
11
+ let!(:current_user) { admin_user }
12
+ let(:organization) { admin_user.organization }
13
+
14
+ before do
15
+ request.env["decidim.current_organization"] = organization
16
+ sign_in current_user, scope: :user
17
+ end
18
+
19
+ describe "role filter" do
20
+ let!(:participant) { create(:user, :confirmed, organization: organization) }
21
+ let!(:department_admin_user) { create(:department_admin, :confirmed, organization: organization) }
22
+ let!(:user_manager) { create(:user, :confirmed, organization: organization, roles: ["user_manager"]) }
23
+ let!(:process_admin) { create(:user, :confirmed, organization: organization) }
24
+ let!(:participatory_process) { create(:participatory_process, organization: organization, title: { en: "A Process space" }) }
25
+ let!(:process_admin_rel) { Decidim::ParticipatoryProcessUserRole.create(role: "admin", user: process_admin, participatory_process: participatory_process) }
26
+ let!(:assembly_admin) { create(:user, :confirmed, organization: organization) }
27
+ let!(:assembly) { create(:assembly, organization: organization, title: { en: "An Assembly space" }) }
28
+ let!(:assembly_admin_rel) { Decidim::AssemblyUserRole.create(role: "admin", user: assembly_admin, assembly: assembly) }
29
+
30
+ subject { controller.filtered_collection }
31
+
32
+ context "when not filtering" do
33
+ it "lists all kind of admin users" do
34
+ get :index, params: {}
35
+
36
+ expect(subject).to include(admin_user, department_admin_user, user_manager, assembly_admin, process_admin)
37
+ expect(subject).not_to include(participant)
38
+ expect(response).to render_template(:index)
39
+ end
40
+ end
41
+
42
+ context "when filtering by process admin email in user term" do
43
+ it "lists the process admin user" do
44
+ get :index, params: { q: { name_or_nickname_or_email_cont: process_admin.email.split("@").first } }
45
+
46
+ expect(subject).to include(process_admin)
47
+ expect(subject).not_to include(admin_user, department_admin_user, user_manager, assembly_admin, participant)
48
+ expect(response).to render_template(:index)
49
+ end
50
+ end
51
+
52
+ context "when filtering by space name" do
53
+ it "lists the space_admins in spaces matching the given term" do
54
+ get :index, params: { q: { name_or_nickname_or_email_cont: "space" }, filter_search: "by_process_name" }
55
+
56
+ expect(subject).to include(process_admin, assembly_admin)
57
+ expect(subject).not_to include(admin_user, department_admin_user, user_manager, participant)
58
+ expect(response).to render_template(:index)
59
+ end
60
+ end
61
+
62
+ context "when filtering by admin role" do
63
+ let(:params) do
64
+ { role: "admin" }
65
+ end
66
+
67
+ it "lists only users with role admin" do
68
+ get :index, params: params
69
+
70
+ expect(subject).to include(admin_user)
71
+ expect(subject).not_to include(department_admin_user, user_manager, process_admin, assembly_admin, participant)
72
+ expect(response).to render_template(:index)
73
+ end
74
+ end
75
+
76
+ context "when filtering by department_admin role" do
77
+ let(:params) do
78
+ { role: "department_admin" }
79
+ end
80
+
81
+ it "lists only users with role department_admin" do
82
+ get :index, params: params
83
+
84
+ expect(subject).to include(department_admin_user)
85
+ expect(subject).not_to include(admin_user, user_manager, process_admin, assembly_admin, participant)
86
+ expect(response).to render_template(:index)
87
+ end
88
+ end
89
+
90
+ context "when filtering by user_manager role" do
91
+ let(:params) do
92
+ { role: "user_manager" }
93
+ end
94
+
95
+ it "lists only users with role user_manager" do
96
+ get :index, params: params
97
+
98
+ expect(subject).to include(user_manager)
99
+ expect(subject).not_to include(admin_user, department_admin_user, process_admin, assembly_admin, participant)
100
+ expect(response).to render_template(:index)
101
+ end
102
+ end
103
+
104
+ context "when filtering by space_admin role" do
105
+ let(:params) do
106
+ { role: "space_admin" }
107
+ end
108
+
109
+ it "lists only users with role space_admin" do
110
+ get :index, params: params
111
+
112
+ expect(subject).to include(process_admin, assembly_admin)
113
+ expect(subject).not_to include(admin_user, department_admin_user, user_manager, participant)
114
+ expect(response).to render_template(:index)
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
data/spec/factories.rb ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/department_admin/test/factories"
4
+ require "decidim/conferences/test/factories"
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe "Overrides" do
6
+ it "check failing tests in Decidim v0.28" do
7
+ # Make test succeed spec/system/department_admin_should_be_able_to_manage_assemblies_spec.rbL73
8
+ # expect(page).to have_current_path decidim_admin_assemblies.assemblies_path(q: { parent_id_eq: parent_assembly&.id })
9
+ expect(Decidim.version).to be < "0.28"
10
+ end
11
+ end
data/spec/i18n_spec.rb ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "i18n/tasks"
4
+
5
+ RSpec.describe "I18n" do
6
+ let(:i18n) { I18n::Tasks::BaseTask.new }
7
+ let(:missing_keys) { i18n.missing_keys }
8
+ let(:unused_keys) { i18n.unused_keys }
9
+
10
+ # All keys from overriding templates come from Decidim so we're having many false positives
11
+ # Probably it will be best tot remove this spec rather than having all keys ignored.
12
+ # it "does not have missing keys" do
13
+ # expect(missing_keys).to be_empty,
14
+ # "Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them"
15
+ # end
16
+
17
+ it "does not have unused keys" do
18
+ expect(unused_keys).to be_empty,
19
+ "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them"
20
+ end
21
+
22
+ it "files are normalized" do
23
+ non_normalized = i18n.non_normalized_paths
24
+ error_message = "The following files need to be normalized:\n" \
25
+ "#{non_normalized.map { |path| " #{path}" }.join("\n")}\n" \
26
+ "Please run `i18n-tasks normalize` to fix"
27
+ expect(non_normalized).to be_empty, error_message
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ describe Area do
7
+ subject(:area) { create(:area) }
8
+
9
+ context "when depending participatory process exist" do
10
+ let!(:department_admin) do
11
+ user = create(:user, :confirmed, organization: area.organization)
12
+ user.roles << "department_admin"
13
+ user.areas << area
14
+ user.save!
15
+ user
16
+ end
17
+
18
+ it "can not be deleted" do
19
+ expect(area.destroy).to be false
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module DepartmentAdmin
7
+ describe Permissions do
8
+ let(:area) { create(:area) }
9
+ let!(:user) do
10
+ create(:department_admin, :confirmed, organization: area.organization, area: area)
11
+ end
12
+
13
+ def should_allow_action(scope, action, subject)
14
+ action = PermissionAction.new(scope: scope, action: action, subject: subject)
15
+ permissions = DepartmentAdmin::Permissions.new(user, action)
16
+ expect(permissions.permissions).to be_allowed
17
+ end
18
+
19
+ def should_allow_action_with_ctx(scope, action, subject, ctx)
20
+ action = PermissionAction.new(scope: scope, action: action, subject: subject)
21
+ permissions = DepartmentAdmin::Permissions.new(user, action, ctx)
22
+ expect(permissions.permissions).to be_allowed
23
+ end
24
+
25
+ context "when user role is department_admin" do
26
+ context "with simple permission actions" do
27
+ it "allows accepted actions" do
28
+ should_allow_action(:admin, :read, :admin_dashboard)
29
+ should_allow_action(:admin, :read, :process_list)
30
+ should_allow_action(:admin, :create, :process)
31
+ should_allow_action(:admin, :read, :process_step)
32
+ should_allow_action(:admin, :create, :process_step)
33
+ should_allow_action(:admin, :read, :assembly_list)
34
+ should_allow_action(:admin, :read, :assembly_user_role)
35
+ should_allow_action(:admin, :create, :assembly)
36
+ should_allow_action(:admin, :index, :newsletter)
37
+ should_allow_action(:admin, :create, :newsletter)
38
+ should_allow_action(:admin, :create, :attachment_collection)
39
+ should_allow_action(:admin, :read, :conference_list)
40
+ should_allow_action(:admin, :read, :conference_user_role)
41
+ should_allow_action(:admin, :create, :conference)
42
+ end
43
+
44
+ it "does not allow non accepted actions" do
45
+ action = PermissionAction.new(scope: :admin, action: :write, subject: :admin_dashboard)
46
+ permissions = DepartmentAdmin::Permissions.new(user, action)
47
+ expect { permissions.permissions.allowed? }.to raise_error(Decidim::PermissionAction::PermissionNotSetError)
48
+ end
49
+ end
50
+
51
+ context "with permission actions with context" do
52
+ context "when acction is allowed and context is space_name" do
53
+ it "allows accepted actions with expected context" do
54
+ should_allow_action_with_ctx(:admin, :enter, :space_area, space_name: :processes)
55
+ should_allow_action_with_ctx(:admin, :enter, :space_area, space_name: :assemblies)
56
+ should_allow_action_with_ctx(:admin, :enter, :space_area, space_name: :conferences)
57
+ end
58
+
59
+ it "does not allow accepted actions with unexpected context" do
60
+ action = PermissionAction.new(scope: :admin, action: :enter, subject: :space_area)
61
+ permissions = DepartmentAdmin::Permissions.new(user, action, space_name: :custom_module)
62
+ expect { permissions.permissions.allowed? }.to raise_error(Decidim::PermissionAction::PermissionNotSetError)
63
+ end
64
+ end
65
+
66
+ context "when acction is allowed and context is process" do
67
+ context "when process has same area as department_admin" do
68
+ let(:process) { create(:participatory_process, organization: area.organization, area: area) }
69
+ let(:assembly) { create(:assembly, organization: area.organization, area: area) }
70
+ let(:conference) { create(:conference, organization: area.organization, area: area) }
71
+
72
+ it "allows accepted actions with expected context" do
73
+ should_allow_action_with_ctx(:admin, :read, :participatory_space, current_participatory_space: process)
74
+ should_allow_action_with_ctx(:admin, :update, :process, process: process)
75
+ pps = ParticipatoryProcessStep.new(participatory_process: process)
76
+ should_allow_action_with_ctx(:admin, :update, :process_step, process_step: pps)
77
+ should_allow_action_with_ctx(:admin, :destroy, :process_step, process_step: pps)
78
+ should_allow_action_with_ctx(:admin, :update, :assembly, assembly: assembly)
79
+ should_allow_action_with_ctx(:admin, :update, :conference, conference: conference)
80
+ # -> {permission_for?(requested_action, :admin, :read, :newsletter, restricted_rsrc: context[:newsletter])},
81
+ end
82
+
83
+ context "when meeting has same area as department_admin" do
84
+ let(:meeting) { create(:meeing, participatory_space: process, area: area) }
85
+
86
+ it "allows accepted actions with expected context" do
87
+ should_allow_action(:admin, :create, :attachment)
88
+ end
89
+ end
90
+ end
91
+
92
+ context "when process has different area as department_admin" do
93
+ let(:process) { create(:participatory_process, organization: area.organization) }
94
+
95
+ it "does not allow accepted actions with unexpected context" do
96
+ action = PermissionAction.new(scope: :admin, action: :update, subject: :process)
97
+ permissions = DepartmentAdmin::Permissions.new(user, action, process: process)
98
+ expect { permissions.permissions.allowed? }.to raise_error(Decidim::PermissionAction::PermissionNotSetError)
99
+ end
100
+ end
101
+ end
102
+
103
+ # context "when acction is allowed and context is component" do
104
+ # context "when component has same area as department_admin" do
105
+ # TODO: complete the test implementation
106
+ # let(:process) { create(:participatory_process, organization: area.organization, area: area) }
107
+ # let(:component) { create(:survey, participatory_space: process) }
108
+
109
+ # it "should allow accepted actions" # do
110
+ # should_allow_action(:admin, :read, :component)
111
+ # should_allow_action(:admin, :create, :component)
112
+ # should_allow_action_with_ctx(:admin, :export, :component_data, current_participatory_space: process)
113
+ # end
114
+ # end
115
+ # end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim::Assemblies
6
+ describe ParentAssembliesForSelect do
7
+ subject { described_class.for(organization, assembly) }
8
+
9
+ let(:organization) { create(:organization) }
10
+ let!(:assembly) { create(:assembly, organization: organization) }
11
+ let!(:assemblies) { create_list(:assembly, 3, organization: organization) }
12
+ let!(:child_assembly) { create(:assembly, :with_parent, parent: assembly, organization: organization) }
13
+ let!(:grand_child_assembly) { create(:assembly, :with_parent, parent: child_assembly, organization: organization) }
14
+
15
+ describe "query" do
16
+ context "when current_user is nil" do
17
+ it "returns assemblies that can be parent" do
18
+ expect(subject.count).to eq(3)
19
+ expect(subject).to match_array(assemblies)
20
+ end
21
+ end
22
+
23
+ context "when current_user is present" do
24
+ subject { described_class.for(organization, assembly, current_user) }
25
+
26
+ let!(:current_user) do
27
+ create(:department_admin, :confirmed, organization: area.organization, area: area)
28
+ end
29
+ let(:area) { create(:area) }
30
+ let!(:assemblies_with_area) { create_list(:assembly, 3, organization: organization, area: area) }
31
+
32
+ it "returns assemblies that can be parent with same current user area" do
33
+ expect(subject.count).to eq(3)
34
+ expect(subject).to match_array(assemblies_with_area)
35
+ end
36
+ end
37
+
38
+ context "when assembly is nil" do
39
+ let(:assembly) { nil }
40
+
41
+ it "returns all assemblies" do
42
+ expected = assemblies
43
+ expected << child_assembly
44
+ expected << grand_child_assembly
45
+
46
+ expect(subject.count).to eq(5)
47
+ expect(subject).to match_array(expected)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/dev"
4
+
5
+ ENV["ENGINE_ROOT"] = File.dirname(__dir__)
6
+
7
+ # require "decidim/admin"
8
+ # require "decidim/core"
9
+ # require "decidim/core/test"
10
+
11
+ Decidim::Dev.dummy_app_path = File.expand_path(File.join("spec", "decidim_dummy_app"))
12
+
13
+ require "decidim/dev/test/base_spec_helper"
14
+
15
+ require "decidim/department_admin"
16
+
17
+ if ENV["SIMPLECOV"]
18
+ require "simplecov"
19
+ SimpleCov.start do
20
+ # `ENGINE_ROOT` holds the name of the engine we're testing.
21
+ # This brings us to the main Decidim folder.
22
+ root File.expand_path(".", ENV.fetch("ENGINE_ROOT", nil))
23
+
24
+ # We make sure we track all Ruby files, to avoid skipping unrequired files
25
+ # We need to include the `../` section, otherwise it only tracks files from the
26
+ # `ENGINE_ROOT` folder for some reason.
27
+ # track_files "../**/*.rb"
28
+
29
+ # We ignore some of the files because they are never tested
30
+ add_filter "/config/"
31
+ add_filter "/db/"
32
+ add_filter "/vendor/"
33
+ add_filter "/spec/"
34
+ add_filter "/test/"
35
+ add_filter %r{^/decidim-[^/]*/lib/decidim/[^/]*/engine.rb}
36
+ add_filter %r{^/decidim-[^/]*/lib/decidim/[^/]*/admin-engine.rb}
37
+ add_filter %r{^/decidim-[^/]*/lib/decidim/[^/]*/component.rb}
38
+ add_filter %r{^/decidim-[^/]*/lib/decidim/[^/]*/participatory_space.rb}
39
+ end
40
+
41
+ SimpleCov.merge_timeout 1800
42
+
43
+ if ENV["CI"]
44
+ require "simplecov-cobertura"
45
+ SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
46
+ end
47
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe "Admin explores processes", type: :system do
6
+ let(:organization) { create(:organization) }
7
+ let!(:area) { create(:area, organization: organization) }
8
+ let!(:process) { create(:participatory_process, organization: organization, area: area) }
9
+
10
+ let!(:admin) { create(:user, :admin, :confirmed, organization: organization) }
11
+
12
+ before do
13
+ switch_to_host(organization.host)
14
+ login_as admin, scope: :user
15
+ end
16
+
17
+ describe "when there are admins of all types" do
18
+ let!(:department_admin) do
19
+ user = create(:user, :confirmed, organization: organization)
20
+ user.roles << "department_admin"
21
+ user.areas << area
22
+ user.save!
23
+ user
24
+ end
25
+
26
+ context "when visiting the list of participatory processes" do
27
+ before do
28
+ visit decidim_admin_participatory_processes.participatory_processes_path
29
+ end
30
+
31
+ it "renders a new column for the process department (aka area)" do
32
+ check_column_header_exists(position: 2, content: "Department/Area")
33
+ check_column_data_exists(position: 2, content: area.name["en"])
34
+ check_column_data_exists(position: 3, content: department_admin.name)
35
+ end
36
+
37
+ it "renders a new column for the department admins in the process"
38
+ it "renders a new column for the process admins in the process"
39
+ end
40
+ end
41
+
42
+ def check_column_header_exists(position: 1, content: "")
43
+ within "#processes .card-section .table-scroll table thead th:nth-child(#{position})" do
44
+ expect(page).to have_content(content)
45
+ end
46
+ end
47
+
48
+ def check_column_data_exists(position: 1, content: "")
49
+ within "#processes .card-section .table-scroll table tbody td:nth-child(#{position})" do
50
+ expect(page).to have_content(content)
51
+ end
52
+ end
53
+ end