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
data/README.md
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
# Decidim::DepartmentAdmin
|
2
|
+
|
3
|
+
This Dedicim's module produces a new \"department admin\" role which restricts the permissions of an Admin into participatory spaces of a given Area.
|
4
|
+
|
5
|
+
The module currently only affects the following participatory spaces and admin blocks:
|
6
|
+
|
7
|
+
- Participatory Processes: administer processes with the same area as the user's one.
|
8
|
+
- Assemblies: administer assemblies with the same area as the user's one.
|
9
|
+
- Newsletters: send newsletters to participants in the spaces with the same area as user's one.
|
10
|
+
- Conferences: administer conferences with the same area as the user's one.
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
DepartmentAdmin will only affect users with the "department admin" role. The rest of the users should behave as usual.
|
15
|
+
|
16
|
+
To create a user with a department admin role, go to admin panel/PARTICIPANTS/Administrators/New Participant. There, select the "Administrador de departament" role, and then the area. Finally Invite the user.
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
Add this line to your application's Gemfile if you would like to always have the latest (edge) version:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
gem "decidim-department_admin", git: "https://github.com/gencat/decidim-module-department-admin.git"
|
24
|
+
```
|
25
|
+
|
26
|
+
Or, add a line like the following to your application's Gemfile if you would like to have the latest stable from the version of your choice, in this case `0.4.x`:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
gem "decidim-department_admin", "~> 0.4.2", git: "https://github.com/gencat/decidim-module-department-admin.git"
|
30
|
+
```
|
31
|
+
|
32
|
+
Edit your app's `config/application.rb` file to enforce railties ordering:
|
33
|
+
```ruby
|
34
|
+
module YourDecidimApp
|
35
|
+
class Application < Rails::Application
|
36
|
+
|
37
|
+
...
|
38
|
+
config.railties_order = [:main_app, ::Decidim::DepartmentAdmin::Engine, :all]
|
39
|
+
...
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
And then execute:
|
46
|
+
|
47
|
+
```bash
|
48
|
+
bundle
|
49
|
+
bundle exec rails decidim_department_admin:install:migrations
|
50
|
+
bundle exec rails db:migrate
|
51
|
+
```
|
52
|
+
|
53
|
+
## Overrides
|
54
|
+
Beware that this module overrides many core features of Decidim. Thus, modified features may have required to override, change or extend source code from Decidim.
|
55
|
+
|
56
|
+
Most of the times the overrides and modifications will be found in `app/decorators`.
|
57
|
+
|
58
|
+
## How it works
|
59
|
+
Although some other artifacts exist, the key places to search for in this module are 3:
|
60
|
+
- lib/decidim/department_admin/engine.rb
|
61
|
+
- app/permissions/decidim/department_admin/permissions.rb
|
62
|
+
- app/decorators
|
63
|
+
|
64
|
+
### Engine
|
65
|
+
The mission of the Engine in this module is to reconfigure the permissions_registry for some artifacts so that they depend upon `Decidim::DepartmentAdmin::Permissions` instead of their standard permissions chain.
|
66
|
+
|
67
|
+
The engine also configures de `app/decorators` directory to be loaded during rails initialization.
|
68
|
+
|
69
|
+
### Custom Permissions
|
70
|
+
The `Decidim::DepartmentAdmin::Permissions` class is the responsible to allow all permissions related with the "departmen admin" role.
|
71
|
+
|
72
|
+
`Decidim::Assemblies::ParticipatorySpacePermissions`, `Decidim::ParticipatoryProcesses::ParticipatorySpacePermissions` and
|
73
|
+
`Decidim::Conferences::ParticipatorySpacePermissions` are subclassing `Decidim::DepartmentAdmin::Permissions` in order to force the permissions classes where they delegate.
|
74
|
+
|
75
|
+
### Decorators
|
76
|
+
Inside `app/decorators` there are all the tricks done in order for department_admin module to work.
|
77
|
+
|
78
|
+
All decorator artifacts are extensions or modifications to the standard Decidim behavior.
|
79
|
+
|
80
|
+
### Temporal fixes
|
81
|
+
|
82
|
+
#### Temporal fix: added & in case role_name check.
|
83
|
+
|
84
|
+
Currently, in the file:
|
85
|
+
- lib/decidim/participatory_space_resourceable.rb
|
86
|
+
we have overridden `user_role_config_for` method, in role_name case check.
|
87
|
+
|
88
|
+
The reason for this, is that this method is called from `user_role_config` in `Decidim::Admin::UserRolesHelper` file, with second param `role_name` that can be nil as it is called as `role&.role`.
|
89
|
+
This happens only when logged in user is Departmental Admin type and this can be possible because this module is only available in this repo.
|
90
|
+
So, to avoid error when role_name passed is nil, we override this param check with a simple `role_name&.to_sym`
|
91
|
+
|
92
|
+
In next versions, this issue will be patched in `decidim/decidim`, so this override could be removed:
|
93
|
+
- lib/decidim/participatory_space_resourceable.rb
|
94
|
+
|
95
|
+
### Run tests
|
96
|
+
|
97
|
+
Create a dummy app in your application (if not present):
|
98
|
+
|
99
|
+
```bash
|
100
|
+
bin/rails decidim:generate_external_test_app
|
101
|
+
cd spec/decidim_dummy_app/
|
102
|
+
bundle exec rails decidim_department_admin:install:migrations
|
103
|
+
RAILS_ENV=test bundle exec rails db:migrate
|
104
|
+
sed -ie '/^ class Application < Rails::Application/a config.railties_order = [:main_app, ::Decidim::DepartmentAdmin::Engine, :all]' config/application.rb
|
105
|
+
```
|
106
|
+
|
107
|
+
This last line modifies dummy_app's `config/application.rb` file to enforce railties ordering, adding:
|
108
|
+
```ruby
|
109
|
+
module DecidimDepartmentAdminTestApp
|
110
|
+
class Application < Rails::Application
|
111
|
+
config.railties_order = [:main_app, ::Decidim::DepartmentAdmin::Engine, :all]
|
112
|
+
...
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
And run tests:
|
119
|
+
|
120
|
+
```bash
|
121
|
+
bundle exec rspec spec
|
122
|
+
```
|
123
|
+
|
124
|
+
## Contributing
|
125
|
+
|
126
|
+
See [Decidim](https://github.com/decidim/decidim).
|
127
|
+
|
128
|
+
## License
|
129
|
+
|
130
|
+
This engine is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
|
131
|
+
|
132
|
+
Authored by [CodiTramuntana](http://coditramuntana.com).
|
data/Rakefile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/dev/common_rake"
|
4
|
+
|
5
|
+
desc "Generates a dummy app for testing"
|
6
|
+
task test_app: "decidim:generate_external_test_app"
|
7
|
+
|
8
|
+
desc "Generates a development app."
|
9
|
+
task development_app: "decidim:generate_external_development_app"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DepartmentAdmin
|
5
|
+
module Admin
|
6
|
+
# This controller is the abstract class from which all other controllers of
|
7
|
+
# this engine inherit.
|
8
|
+
#
|
9
|
+
# Note that it inherits from `Decidim::Admin::Components::BaseController`, which
|
10
|
+
# override its layout and provide all kinds of useful methods.
|
11
|
+
class ApplicationController < Decidim::Admin::Components::BaseController
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DepartmentAdmin
|
5
|
+
# This controller is the abstract class from which all other controllers of
|
6
|
+
# this engine inherit.
|
7
|
+
#
|
8
|
+
# Note that it inherits from `Decidim::Components::BaseController`, which
|
9
|
+
# override its layout and provide all kinds of useful methods.
|
10
|
+
class ApplicationController < Decidim::Components::BaseController
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency "decidim/admin/newsletters_controller"
|
4
|
+
|
5
|
+
module Decidim::Admin::NewslettersControllerDecorator
|
6
|
+
# Sort Admins by role and area
|
7
|
+
def self.decorate
|
8
|
+
::Decidim::Admin::NewslettersController.class_eval do
|
9
|
+
alias_method :original_collection, :collection
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def collection
|
14
|
+
return original_collection unless current_user.department_admin?
|
15
|
+
|
16
|
+
@collection ||= Decidim::Newsletter.where(organization: current_organization)
|
17
|
+
.joins(author: :areas)
|
18
|
+
.where(department_admin_areas: { decidim_area_id: current_user_areas.pluck(:id) })
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_user_areas
|
22
|
+
return unless current_user.department_admin?
|
23
|
+
|
24
|
+
current_user.areas
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
::Decidim::Admin::NewslettersControllerDecorator.decorate
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency "decidim/admin/users_controller"
|
4
|
+
|
5
|
+
# This decorator adds the capability to the controller to query users
|
6
|
+
# filtering by User role `department_admin`.
|
7
|
+
module Decidim::Admin::UsersControllerDecorator
|
8
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
9
|
+
# rubocop: disable Metrics/PerceivedComplexity
|
10
|
+
def self.decorate
|
11
|
+
# Sort Admins by role and area
|
12
|
+
::Decidim::Admin::UsersController.class_eval do
|
13
|
+
alias_method :original_collection, :collection
|
14
|
+
|
15
|
+
include ::Decidim::DepartmentAdmin::ApplicationHelper
|
16
|
+
helper_method :roles_with_title, :filtered_collection
|
17
|
+
|
18
|
+
before_action :read_params, only: :index
|
19
|
+
|
20
|
+
def read_params
|
21
|
+
@role = params[:role]
|
22
|
+
@by_process_name = params[:filter_search] == "by_process_name"
|
23
|
+
term = params.dig(:q, :name_or_nickname_or_email_cont)
|
24
|
+
@search_text = term
|
25
|
+
end
|
26
|
+
|
27
|
+
def collection
|
28
|
+
@collection ||= begin
|
29
|
+
filtered = if @by_process_name
|
30
|
+
::Decidim::Admin::UserAdminBySpaceNameFilter.for(@search_text, current_organization, current_locale)
|
31
|
+
else
|
32
|
+
::Decidim::Admin::UserAdminFilter.for(original_collection, @search_text, @role, current_organization)
|
33
|
+
end
|
34
|
+
if current_user.department_admin?
|
35
|
+
filtered.joins(:areas)
|
36
|
+
.where("'department_admin' = ANY(roles)")
|
37
|
+
.where("decidim_areas.id": current_user.areas.pluck(:id))
|
38
|
+
else
|
39
|
+
filtered
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# override decidim-admin/app/controllers/concerns/decidim/admin/filterable.rb#filtered_collection default behavior.
|
45
|
+
def filtered_collection
|
46
|
+
@filtered_collection ||= begin
|
47
|
+
users = @by_process_name ? collection : query.result
|
48
|
+
sorted_users = users.uniq.sort { |u_1, u_2| "#{u_1.active_role}||#{u_1.areas.first&.name}" <=> "#{u_2.active_role}||#{u_2.areas.first&.name}" }
|
49
|
+
paginate(Kaminari.paginate_array(sorted_users))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def show
|
54
|
+
locale = params[:locale] || "ca"
|
55
|
+
@user ||= original_collection.find(params[:id])
|
56
|
+
@spaces = []
|
57
|
+
@user.participatory_processes.each do |process|
|
58
|
+
type = if process.participatory_process_group
|
59
|
+
process.participatory_process_group&.title&.[](locale).presence || process.participatory_process_group&.title&.[]("ca")
|
60
|
+
else
|
61
|
+
t("models.user.fields.process_type", scope: "decidim.admin")
|
62
|
+
end
|
63
|
+
process_title = process.title[locale]
|
64
|
+
process_title = process.title["ca"] if process_title.blank?
|
65
|
+
|
66
|
+
@spaces.push("title" => process_title,
|
67
|
+
"type" => type,
|
68
|
+
"area" => process.area.nil? ? "" : process.area&.name&.[](locale),
|
69
|
+
"created_at" => process.created_at,
|
70
|
+
"private" => process.private_space?,
|
71
|
+
"published" => process.published?)
|
72
|
+
end
|
73
|
+
|
74
|
+
@user.assemblies.each do |assembly|
|
75
|
+
area_name = if assembly.area && assembly.area.name
|
76
|
+
assembly.area.name[locale]
|
77
|
+
else
|
78
|
+
""
|
79
|
+
end
|
80
|
+
|
81
|
+
assembly_title = assembly.title[locale]
|
82
|
+
assembly_title = assembly.title["ca"] if assembly_title.blank?
|
83
|
+
|
84
|
+
@spaces.push("title" => assembly_title,
|
85
|
+
"type" => t("models.user.fields.assembly_type", scope: "decidim.admin"),
|
86
|
+
"area" => area_name,
|
87
|
+
"created_at" => assembly.created_at,
|
88
|
+
"private" => assembly.private_space?,
|
89
|
+
"published" => assembly.published?)
|
90
|
+
end
|
91
|
+
|
92
|
+
if Decidim::DepartmentAdmin.conferences_defined?
|
93
|
+
@user.conferences.each do |conference|
|
94
|
+
area_name = conference.area&.name.try(:[], locale) || ""
|
95
|
+
|
96
|
+
conference_title = conference.title[locale]
|
97
|
+
conference_title = conference.title["ca"] if conference_title.blank?
|
98
|
+
|
99
|
+
@spaces.push("title" => conference_title,
|
100
|
+
"type" => t("models.user.fields.conference_type", scope: "decidim.admin"),
|
101
|
+
"area" => area_name,
|
102
|
+
"created_at" => conference.created_at,
|
103
|
+
"private" => conference.private_space?,
|
104
|
+
"published" => conference.published?)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# rubocop: disable Style/NestedTernaryOperator
|
109
|
+
if (params[:sort_column] == "published" || params[:sort_column] == "private") && params[:sort_order] == "asc"
|
110
|
+
@spaces.sort! { |x, y| x[params[:sort_column]] ? 0 : (1 <=> y[params[:sort_column]] ? 0 : 1) }
|
111
|
+
elsif (params[:sort_column] == "published" || params[:sort_column] == "private") && params[:sort_order] == "desc"
|
112
|
+
@spaces.sort! { |x, y| y[params[:sort_column]] ? 0 : 1 <=> x[params[:sort_column]] ? 0 : 1 }
|
113
|
+
elsif params[:sort_column] && params[:sort_order] && params[:sort_order] == "asc"
|
114
|
+
@spaces.sort! { |x, y| x[params[:sort_column]] <=> y[params[:sort_column]] }
|
115
|
+
elsif params[:sort_column] && params[:sort_order] && params[:sort_order] == "desc"
|
116
|
+
@spaces.sort! { |x, y| y[params[:sort_column]] <=> x[params[:sort_column]] }
|
117
|
+
else
|
118
|
+
@spaces.sort! { |x, y| y["title"] <=> x["title"] }
|
119
|
+
end
|
120
|
+
# rubocop: enable Style/NestedTernaryOperator
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
125
|
+
# rubocop: enable Metrics/PerceivedComplexity
|
126
|
+
end
|
127
|
+
|
128
|
+
::Decidim::Admin::UsersControllerDecorator.decorate
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency "decidim/area"
|
4
|
+
|
5
|
+
module Decidim::AreaDecorator
|
6
|
+
def self.decorate
|
7
|
+
Decidim::Area.class_eval do
|
8
|
+
before_destroy :abort_if_department_admins
|
9
|
+
|
10
|
+
has_and_belongs_to_many :users,
|
11
|
+
-> { where('\'department_admin\'=ANY("decidim_users"."roles")') },
|
12
|
+
join_table: :department_admin_areas,
|
13
|
+
foreign_key: :decidim_area_id,
|
14
|
+
association_foreign_key: :decidim_user_id,
|
15
|
+
validate: false
|
16
|
+
|
17
|
+
has_many :participatory_process,
|
18
|
+
class_name: "ParticipatoryProcess",
|
19
|
+
foreign_key: "decidim_department_id"
|
20
|
+
|
21
|
+
has_many :assemblies,
|
22
|
+
class_name: "Assemblies",
|
23
|
+
foreign_key: "decidim_area_id"
|
24
|
+
|
25
|
+
if Decidim::DepartmentAdmin.conferences_defined?
|
26
|
+
has_many :conferences,
|
27
|
+
class_name: "Conferences",
|
28
|
+
foreign_key: "decidim_area_id"
|
29
|
+
end
|
30
|
+
|
31
|
+
def has_department_admins?
|
32
|
+
Decidim::User.where(organization: organization).any? do |u|
|
33
|
+
u.areas.exists?(id)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def abort_if_department_admins
|
38
|
+
throw(:abort) if has_department_admins?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
::Decidim::AreaDecorator.decorate
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim::Assemblies::Admin::AssembliesControllerDecorator
|
4
|
+
#
|
5
|
+
# This decorator adds the capability to the controller to query assemblies
|
6
|
+
# filtering by User role `department_admin`.
|
7
|
+
#
|
8
|
+
def self.decorate
|
9
|
+
Decidim::Assemblies::Admin::AssembliesController.class_eval do
|
10
|
+
private
|
11
|
+
|
12
|
+
alias_method :original_organization_assemblies, :collection
|
13
|
+
|
14
|
+
def collection
|
15
|
+
if current_user.department_admin?
|
16
|
+
::Decidim::Assemblies::AssembliesWithUserRole.for(current_user)
|
17
|
+
else
|
18
|
+
original_organization_assemblies
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
::Decidim::Assemblies::Admin::AssembliesControllerDecorator.decorate
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim::Assemblies::Admin::AssembliesHelperDecorator
|
4
|
+
#
|
5
|
+
# This decorator sends current_user as argument when it's a department admin.
|
6
|
+
#
|
7
|
+
def self.decorate
|
8
|
+
Decidim::Assemblies::Admin::AssembliesHelper.class_eval do
|
9
|
+
alias_method :parent_assemblies_for_select_original, :parent_assemblies_for_select
|
10
|
+
|
11
|
+
# Public: A collection of Assemblies that can be selected as parent
|
12
|
+
# assemblies for another assembly; to be used in forms.
|
13
|
+
def parent_assemblies_for_select
|
14
|
+
if current_user.department_admin?
|
15
|
+
@parent_assemblies_for_select ||= Decidim::Assemblies::ParentAssembliesForSelect.for(current_organization, current_assembly, current_user)
|
16
|
+
else
|
17
|
+
parent_assemblies_for_select_original
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
::Decidim::Assemblies::Admin::AssembliesHelperDecorator.decorate
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim::Assemblies::CreateAssemblyDecorator
|
4
|
+
# Intercepts the `call` method and forces the Area of the user if it is a
|
5
|
+
# department_admin user.
|
6
|
+
def self.decorate
|
7
|
+
Decidim::Assemblies::Admin::CreateAssembly.class_eval do
|
8
|
+
alias_method :original_call, :call
|
9
|
+
|
10
|
+
def call
|
11
|
+
author = form.current_user
|
12
|
+
form.area_id = author.areas.first.id if author.department_admin?
|
13
|
+
original_call
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
::Decidim::Assemblies::CreateAssemblyDecorator.decorate
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim::Assemblies::ParentAssembliesForSelectDecorator
|
4
|
+
# This decorator adds current_user as an argument to be able to check
|
5
|
+
# it's department in the query and filter the assemblies by area.
|
6
|
+
def self.decorate
|
7
|
+
Decidim::Assemblies::ParentAssembliesForSelect.class_eval do
|
8
|
+
# Syntactic sugar to initialize the class and return the queried objects.
|
9
|
+
def self.for(organization, assembly, current_user = nil)
|
10
|
+
new(organization, assembly, current_user).query
|
11
|
+
end
|
12
|
+
|
13
|
+
# Initializes the class.
|
14
|
+
def initialize(organization, assembly, current_user)
|
15
|
+
@organization = organization
|
16
|
+
@assembly = assembly
|
17
|
+
@current_user = current_user
|
18
|
+
end
|
19
|
+
|
20
|
+
# Finds the available assemblies
|
21
|
+
#
|
22
|
+
# Returns an ActiveRecord::Relation.
|
23
|
+
def query
|
24
|
+
available_assemblies = if @current_user.present? && @current_user.department_admin?
|
25
|
+
Decidim::Assembly.where(area: @current_user.areas).where.not(id: @assembly)
|
26
|
+
else
|
27
|
+
Decidim::Assembly.where(organization: @organization).where.not(id: @assembly)
|
28
|
+
end
|
29
|
+
|
30
|
+
return available_assemblies if @assembly.blank?
|
31
|
+
|
32
|
+
available_assemblies.where.not(id: descendant_ids)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
::Decidim::Assemblies::ParentAssembliesForSelectDecorator.decorate
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim::Assemblies::PermissionsDecorator
|
4
|
+
def self.decorate
|
5
|
+
Decidim::Assemblies::Permissions.class_eval do
|
6
|
+
# Intercept the `has_manageable_assemblies?` method
|
7
|
+
# always returns true if the user is a department_admin. Otherwise delegates to the original method.
|
8
|
+
# This is a fix to avoid permissions crashing when there are no assemblies with the user's area.
|
9
|
+
alias_method :original_has_manageable_assemblies?, :has_manageable_assemblies?
|
10
|
+
|
11
|
+
# rubocop: disable Lint/UnusedMethodArgument
|
12
|
+
def has_manageable_assemblies?(role: :any)
|
13
|
+
return unless user
|
14
|
+
|
15
|
+
user.department_admin? || original_has_manageable_assemblies?
|
16
|
+
end
|
17
|
+
# rubocop: enable Lint/UnusedMethodArgument
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
::Decidim::Assemblies::PermissionsDecorator.decorate
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim::Assemblies::UpdateAssemblyDecorator
|
4
|
+
# Intercepts the `call` method and forces the Area of the user if it is a
|
5
|
+
# department_admin user.
|
6
|
+
def self.decorate
|
7
|
+
Decidim::Assemblies::Admin::UpdateAssembly.class_eval do
|
8
|
+
alias_method :original_call, :call
|
9
|
+
|
10
|
+
def call
|
11
|
+
author = form.current_user
|
12
|
+
form.area_id = author.areas.first.id if author.department_admin?
|
13
|
+
original_call
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
::Decidim::Assemblies::UpdateAssemblyDecorator.decorate
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency "decidim/assembly"
|
4
|
+
|
5
|
+
module Decidim::AssembliesDecorator
|
6
|
+
#
|
7
|
+
# This decorator adds required associations between Decidim::ParticipatoryProcess and Departaments.
|
8
|
+
#
|
9
|
+
def self.decorate
|
10
|
+
Decidim::Assembly.class_eval do
|
11
|
+
has_and_belongs_to_many :users_with_any_role,
|
12
|
+
class_name: "Decidim::User",
|
13
|
+
join_table: :decidim_assembly_user_roles,
|
14
|
+
foreign_key: :decidim_assembly_id,
|
15
|
+
association_foreign_key: :decidim_user_id,
|
16
|
+
validate: false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
::Decidim::AssembliesDecorator.decorate
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim::AssembliesWithUserRoleDecorator
|
4
|
+
#
|
5
|
+
# This decorator adds the capability to query participatory_processes
|
6
|
+
# filtering by User role `department_admin`.
|
7
|
+
#
|
8
|
+
def self.decorate
|
9
|
+
Decidim::Assemblies::AssembliesWithUserRole.class_eval do
|
10
|
+
private
|
11
|
+
|
12
|
+
alias_method :assembly_ids_by_assemblies_user_table, :assembly_ids
|
13
|
+
|
14
|
+
def assembly_ids
|
15
|
+
ids = [assembly_ids_by_assemblies_user_table]
|
16
|
+
if user&.department_admin?
|
17
|
+
ids << ::Decidim::Assembly
|
18
|
+
.where("decidim_area_id" => user.areas.pluck(:id)).pluck(:id)
|
19
|
+
end
|
20
|
+
|
21
|
+
::Decidim::Assembly.where(id: ids.flatten.uniq)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
::Decidim::AssembliesWithUserRoleDecorator.decorate
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim::ConferenceFormDecorator
|
4
|
+
#
|
5
|
+
# This decorator adds the attribute area_id to the ConferenceForm and
|
6
|
+
# extends it with utility methods for the view and command.
|
7
|
+
#
|
8
|
+
def self.decorate
|
9
|
+
return unless Decidim::DepartmentAdmin.conferences_defined?
|
10
|
+
|
11
|
+
Decidim::Conferences::Admin::ConferenceForm.class_eval do
|
12
|
+
attribute :area_id, Integer
|
13
|
+
|
14
|
+
validates :area, presence: true, if: proc { |object| object.area_id.present? }
|
15
|
+
|
16
|
+
def area
|
17
|
+
@area ||= current_organization.areas.find_by(id: area_id)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
::Decidim::ConferenceFormDecorator.decorate
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim::Conferences::Admin::ConferencesControllerDecorator
|
4
|
+
#
|
5
|
+
# This decorator adds the capability to the controller to query conferences
|
6
|
+
# filtering by User role `department_admin`.
|
7
|
+
#
|
8
|
+
def self.decorate
|
9
|
+
return unless Decidim::DepartmentAdmin.conferences_defined?
|
10
|
+
|
11
|
+
Decidim::Conferences::Admin::ConferencesController.class_eval do
|
12
|
+
private
|
13
|
+
|
14
|
+
alias_method :original_collection, :collection
|
15
|
+
|
16
|
+
def collection
|
17
|
+
@collection ||= if current_user.admin?
|
18
|
+
original_collection
|
19
|
+
else
|
20
|
+
::Decidim::Conferences::ConferencesWithUserRole.for(current_user)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
::Decidim::Conferences::Admin::ConferencesControllerDecorator.decorate
|