decidim-department_admin 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +132 -0
- data/Rakefile +9 -0
- data/app/controllers/decidim/department_admin/admin/application_controller.rb +15 -0
- data/app/controllers/decidim/department_admin/application_controller.rb +13 -0
- data/app/decorators/decidim/admin/newsletters_controller_decorator.rb +30 -0
- data/app/decorators/decidim/admin/users_controller_decorator.rb +128 -0
- data/app/decorators/decidim/area_decorator.rb +44 -0
- data/app/decorators/decidim/assemblies/admin/assemblies_controller_decorator.rb +25 -0
- data/app/decorators/decidim/assemblies/admin/assemblies_helper_decorator.rb +24 -0
- data/app/decorators/decidim/assemblies/create_assembly_decorator.rb +19 -0
- data/app/decorators/decidim/assemblies/parent_assemblies_for_select_decorator.rb +38 -0
- data/app/decorators/decidim/assemblies/permissions_decorator.rb +22 -0
- data/app/decorators/decidim/assemblies/update_assembly_decorator.rb +19 -0
- data/app/decorators/decidim/assemblies_decorator.rb +21 -0
- data/app/decorators/decidim/assemblies_with_user_role_decorator.rb +27 -0
- data/app/decorators/decidim/conference_form_decorator.rb +23 -0
- data/app/decorators/decidim/conferences/admin/conferences_controller_decorator.rb +27 -0
- data/app/decorators/decidim/conferences/create_conference_decorator.rb +51 -0
- data/app/decorators/decidim/conferences/permissions_decorator.rb +24 -0
- data/app/decorators/decidim/conferences/update_conference_decorator.rb +21 -0
- data/app/decorators/decidim/conferences_decorator.rb +27 -0
- data/app/decorators/decidim/conferences_with_user_role_decorator.rb +29 -0
- data/app/decorators/decidim/decidim_form_helper_decorator.rb +23 -0
- data/app/decorators/decidim/invite_user_decorator.rb +56 -0
- data/app/decorators/decidim/invite_user_form_decorator.rb +45 -0
- data/app/decorators/decidim/newsletter_decorator.rb +20 -0
- data/app/decorators/decidim/newsletters_helper_decorator.rb +44 -0
- data/app/decorators/decidim/participatory_process_decorator.rb +21 -0
- data/app/decorators/decidim/participatory_process_group_decorator.rb +17 -0
- data/app/decorators/decidim/participatory_processes/admin/participatory_processes_controller_decorator.rb +25 -0
- data/app/decorators/decidim/participatory_processes/create_participatory_process_decorator.rb +19 -0
- data/app/decorators/decidim/participatory_processes/permissions_decorator.rb +22 -0
- data/app/decorators/decidim/participatory_processes/update_participatory_process_decorator.rb +19 -0
- data/app/decorators/decidim/participatory_processes_with_user_role_decorator.rb +27 -0
- data/app/decorators/decidim/user_decorator.rb +59 -0
- data/app/decorators/lib/decidim/participatory_space_resourceable_decorator.rb +36 -0
- data/app/helpers/decidim/admin/user_roles_helper.rb +25 -0
- data/app/helpers/decidim/department_admin/application_helper.rb +54 -0
- data/app/models/decidim/participatory_space_role_config/department_admin.rb +8 -0
- data/app/overrides/decidim/admin/shared/add_radio_buttons_to_filters.rb +6 -0
- data/app/packs/entrypoints/decidim_department_admin.js +4 -0
- data/app/packs/entrypoints/decidim_department_admin.scss +1 -0
- data/app/packs/images/decidim/department_admin/icon.svg +1 -0
- data/app/packs/stylesheets/decidim/admin/department_admin.scss +5 -0
- data/app/permissions/decidim/assemblies/participatory_space_permissions.rb +14 -0
- data/app/permissions/decidim/conferences/participatory_space_permissions.rb +17 -0
- data/app/permissions/decidim/department_admin/permissions.rb +240 -0
- data/app/permissions/decidim/participatory_processes/participatory_space_permissions.rb +14 -0
- data/app/queries/decidim/admin/user_admin_by_space_name_filter.rb +67 -0
- data/app/queries/decidim/admin/user_admin_filter.rb +50 -0
- data/app/views/decidim/admin/users/_filters.html.erb +28 -0
- data/app/views/decidim/admin/users/_form.html.erb +30 -0
- data/app/views/decidim/admin/users/index.html.erb +93 -0
- data/app/views/decidim/admin/users/show.html.erb +99 -0
- data/app/views/decidim/assemblies/admin/assemblies/index.html.erb +147 -0
- data/app/views/decidim/conferences/admin/conferences/_form.html.erb +127 -0
- data/app/views/decidim/conferences/admin/conferences/index.html.erb +85 -0
- data/app/views/decidim/participatory_processes/admin/participatory_processes/index.html.erb +160 -0
- data/config/assets.rb +27 -0
- data/config/i18n-tasks.yml +148 -0
- data/config/initializers/user_roles.rb +4 -0
- data/config/locales/ca.yml +61 -0
- data/config/locales/cs.yml +46 -0
- data/config/locales/en.yml +61 -0
- data/config/locales/es.yml +61 -0
- data/db/migrate/20190328130102_create_department_admin_areas.rb +10 -0
- data/db/migrate/20210420143021_add_area_to_conferences.rb +7 -0
- data/lib/decidim/department_admin/admin.rb +10 -0
- data/lib/decidim/department_admin/admin_engine.rb +27 -0
- data/lib/decidim/department_admin/engine.rb +137 -0
- data/lib/decidim/department_admin/test/factories.rb +17 -0
- data/lib/decidim/department_admin/version.rb +11 -0
- data/lib/decidim/department_admin.rb +15 -0
- data/spec/commands/decidim/admin/deliver_newsletter_spec.rb +175 -0
- data/spec/commands/decidim/invite_user_spec.rb +42 -0
- data/spec/controllers/decidim/admin/users_controller_spec.rb +119 -0
- data/spec/factories.rb +4 -0
- data/spec/features/check_overrides_spec.rb +11 -0
- data/spec/i18n_spec.rb +29 -0
- data/spec/models/decidim/area_spec.rb +23 -0
- data/spec/permissions/decidim/department_admin/department_admin_permissions_spec.rb +120 -0
- data/spec/queries/parent_assemblies_for_select_spec.rb +52 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/system/admin_explores_processes_spec.rb +53 -0
- data/spec/system/admin_invite_department_admin_spec.rb +118 -0
- data/spec/system/department_admin_manages_newsletters_spec.rb +237 -0
- data/spec/system/department_admin_should_be_able_to_access_admin_dashboard_spec.rb +75 -0
- data/spec/system/department_admin_should_be_able_to_manage_assemblies_spec.rb +99 -0
- data/spec/system/department_admin_should_be_able_to_manage_conferences_spec.rb +74 -0
- data/spec/system/department_admin_should_be_able_to_manage_processes_spec.rb +117 -0
- data/spec/system/department_admin_should_be_able_to_see_only_assemblies_from_her_area_spec.rb +46 -0
- data/spec/system/department_admin_should_be_able_to_see_only_newsletters_from_her_area_spec.rb +53 -0
- data/spec/system/department_admin_should_be_able_to_see_only_processes_from_her_area_spec.rb +50 -0
- 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,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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|