decidim-department_admin 0.8.0

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 (76) 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 +52 -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 +33 -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 +7 -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 +32 -0
  54. data/app/views/decidim/admin/users/_form.html.erb +36 -0
  55. data/app/views/decidim/admin/users/index.html.erb +91 -0
  56. data/app/views/decidim/admin/users/show.html.erb +98 -0
  57. data/app/views/decidim/assemblies/admin/assemblies/index.html.erb +139 -0
  58. data/app/views/decidim/conferences/admin/conferences/_form.html.erb +134 -0
  59. data/app/views/decidim/conferences/admin/conferences/index.html.erb +78 -0
  60. data/app/views/decidim/participatory_processes/admin/participatory_processes/index.html.erb +117 -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 +136 -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. metadata +189 -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:).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