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
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DepartmentAdmin
5
+ # Custom helpers, scoped to the department_admin engine.
6
+ #
7
+ module ApplicationHelper
8
+ include ::Decidim::TranslatableAttributes
9
+
10
+ # rubocop: disable Rails/HelperInstanceVariable
11
+ def roles_with_title(user)
12
+ roles_with_title = user.roles.collect { |role| [role, ""] }
13
+ # if user had participatory processes then add role of process admin
14
+ user_participatory_processes_filtered(user, current_locale, @search_text).each do |participatory_process|
15
+ roles_with_title << ["process_admin", translated_attribute(participatory_process.title)]
16
+ end
17
+ # if user is admin then add admin role
18
+ roles_with_title << ["admin", ""] if user.admin?
19
+ # if user had assemblies then add role of assembly admin
20
+ user_assemblies_filtered(user, current_locale, @search_text).each do |assembly|
21
+ roles_with_title << ["assembly_admin", translated_attribute(assembly.title)]
22
+ end
23
+ # if user had conferences then add role of conference admin
24
+ user_conferences_filtered(user, current_locale, @search_text).each do |conference|
25
+ roles_with_title << ["conference_admin", translated_attribute(conference.title)]
26
+ end
27
+ roles_with_title
28
+ end
29
+
30
+ private
31
+
32
+ def user_participatory_processes_filtered(user, _locale, search_text)
33
+ query = user.participatory_processes
34
+ query = query.where("lower(title->>?) like lower(?)", current_locale, "%#{search_text}%") if @by_process_name && search_text.present?
35
+ query
36
+ end
37
+
38
+ def user_assemblies_filtered(user, _locale, search_text)
39
+ query = user.assemblies
40
+ query = query.where("lower(title->>?) like lower(?)", current_locale, "%#{search_text}%") if @by_process_name && search_text.present?
41
+ query
42
+ end
43
+
44
+ def user_conferences_filtered(user, _locale, search_text)
45
+ return [] unless Decidim::DepartmentAdmin.conferences_defined?
46
+
47
+ query = user.conferences
48
+ query = query.where("lower(title->>?) like lower(?)", current_locale, "%#{search_text}%") if @by_process_name && search_text.present?
49
+ query
50
+ end
51
+ # rubocop: enable Rails/HelperInstanceVariable
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module ParticipatorySpaceRoleConfig
5
+ class DepartmentAdmin < Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ Deface::Override.new(virtual_path: "decidim/admin/shared/_filters",
4
+ name: "add_radio_buttons_to_filters",
5
+ insert_after: "div.input-group",
6
+ partial: "decidim/admin/users/filters")
@@ -0,0 +1,4 @@
1
+ // Images
2
+ require.context("../images", true)
3
+
4
+ import "entrypoints/decidim_department_admin.scss";
@@ -0,0 +1 @@
1
+ @import "stylesheets/decidim/admin/department_admin";
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 35"><path d="M17.5 35A17.5 17.5 0 1 1 35 17.5 17.52 17.52 0 0 1 17.5 35zm0-33.06A15.56 15.56 0 1 0 33.06 17.5 15.57 15.57 0 0 0 17.5 1.94zm9.5 13.7H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zm0 3.68H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zM22.26 23H8a1 1 0 0 1 0-1.94h14.26a1 1 0 0 1 0 1.94z"/></svg>
@@ -0,0 +1,7 @@
1
+ .department-admin-filter {
2
+ margin-left: 20px;
3
+
4
+ .dropdown {
5
+ z-index: 0 !important;
6
+ }
7
+ }
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ class ParticipatorySpacePermissions < Decidim::DepartmentAdmin::Permissions
6
+ def initialize(*)
7
+ # This are the same permissions as Decidim's assemblies space.
8
+ # Right now are the same for admin and public views
9
+ self.class.delegate_chain = [Decidim::Assemblies::Permissions]
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Conferences
5
+ parent_class = Decidim::DepartmentAdmin.conferences_defined? ? Decidim::DepartmentAdmin::Permissions : Object
6
+ class ParticipatorySpacePermissions < parent_class
7
+ def initialize(*)
8
+ if Decidim::DepartmentAdmin.conferences_defined?
9
+ # This are the same permissions as Decidim's conferences space.
10
+ # Right now are the same for admin and public views
11
+ self.class.delegate_chain = [Decidim::Conferences::Permissions]
12
+ end
13
+ super
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,240 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DepartmentAdmin
5
+ class Permissions < Decidim::DefaultPermissions
6
+ class << self
7
+ attr_writer :delegate_chain, :configurable_checks
8
+ end
9
+
10
+ class << self
11
+ attr_reader :delegate_chain, :configurable_checks
12
+ end
13
+
14
+ def delegate_chain
15
+ self.class.delegate_chain
16
+ end
17
+
18
+ # Applications with custom modules can configure their checks in an initializer.
19
+ # The checks will be executed in `has_permissions?`, and the syntax should be like:
20
+ #
21
+ # <code>
22
+ # Decidim::DepartmentAdmin::Permissions.configurable_checks= [
23
+ # {permission_for?: [:admin, :enter, :space_area, space_name: :courses]}
24
+ # ]
25
+ # </code>
26
+ def configurable_checks
27
+ ::Decidim::DepartmentAdmin::Permissions.configurable_checks || []
28
+ end
29
+
30
+ def permissions
31
+ # byebug if same_action?(permission_action, :admin, :read, :global_moderation)
32
+
33
+ current_permission_action = permission_action
34
+ if permission_action.scope == :admin && user&.department_admin?
35
+ current_permission_action = apply_department_admin_permissions!
36
+ elsif delegate_chain.present?
37
+ # not admin or not a department_admin, use the standard permissions
38
+ delegate_chain.inject(permission_action) do |injected_permission_action, permission_class|
39
+ permission_class.new(user, injected_permission_action, context).permissions
40
+ end
41
+ else
42
+ super
43
+ end
44
+
45
+ current_permission_action
46
+ end
47
+
48
+ def apply_department_admin_permissions!
49
+ # avoid having PermissionCannotBeDisallowedError if permission was already disallowed in the chain
50
+ new_permission_action = permission_action.dup
51
+ if has_permission?(new_permission_action)
52
+ new_permission_action.allow!
53
+ new_permission_action
54
+ elsif delegate_chain.present?
55
+ # if department_admin has no permissions let's apply the default permissions
56
+ delegate_chain.inject(permission_action) do |injected_permission_action, permission_class|
57
+ permission_class.new(user, injected_permission_action, context).permissions
58
+ end
59
+ else
60
+ permission_action
61
+ end
62
+ end
63
+
64
+ def has_permission?(requested_action)
65
+ default_checks = [
66
+ -> { permission_for?(requested_action, :admin, :read, :admin_dashboard) },
67
+ -> { permission_for?(requested_action, :public, :read, :admin_dashboard) },
68
+
69
+ -> { permission_for_current_space?(requested_action) },
70
+
71
+ # PARTICIPATORY PROCESSES
72
+ -> { permission_for?(requested_action, :admin, :enter, :space_area, space_name: :processes) },
73
+ -> { permission_for?(requested_action, :admin, :read, :process_list) },
74
+ -> { permission_for?(requested_action, :admin, :create, :process) },
75
+ -> { same_area_permission_for?(requested_action, :admin, :preview, :process, restricted_rsrc: context[:process]) },
76
+ -> { same_area_permission_for?(requested_action, :admin, :update, :process, restricted_rsrc: context[:process]) },
77
+ -> { same_area_permission_for?(requested_action, :admin, :publish, :process, restricted_rsrc: context[:process]) },
78
+ -> { same_area_permission_for?(requested_action, :admin, :unpublish, :process, restricted_rsrc: context[:process]) },
79
+ -> { permission_for?(requested_action, :admin, :import, :process) },
80
+
81
+ # STEPS
82
+ -> { permission_for?(requested_action, :admin, :read, :process_step) },
83
+ -> { permission_for?(requested_action, :admin, :create, :process_step) },
84
+ -> { same_area_permission_for?(requested_action, :admin, :update, :process_step, restricted_rsrc: context[:process_step]&.participatory_process) },
85
+ -> { same_area_permission_for?(requested_action, :admin, :activate, :process_step, restricted_rsrc: context[:process_step]&.participatory_process) },
86
+ -> { same_area_permission_for?(requested_action, :admin, :destroy, :process_step, restricted_rsrc: context[:process_step]&.participatory_process) },
87
+ # COMPONENTS
88
+ -> { permission_for?(requested_action, :admin, :read, :component) },
89
+ -> { permission_for?(requested_action, :admin, :create, :component) },
90
+ -> { same_area_permission_for?(requested_action, :admin, :update, :component, restricted_rsrc: context[:component]&.participatory_space) },
91
+ -> { same_area_permission_for?(requested_action, :admin, :manage, :component, restricted_rsrc: context[:component]&.participatory_space) },
92
+ -> { same_area_permission_for?(requested_action, :admin, :destroy, :component, restricted_rsrc: context[:component]&.participatory_space) },
93
+ -> { same_area_permission_for?(requested_action, :admin, :publish, :component, restricted_rsrc: context[:component]&.participatory_space) },
94
+ -> { same_area_permission_for?(requested_action, :admin, :unpublish, :component, restricted_rsrc: context[:component]&.participatory_space) },
95
+ -> { same_area_permission_for?(requested_action, :admin, :export, :component_data, restricted_rsrc: context[:component]&.participatory_space) },
96
+ # CATEGORIES
97
+ -> { permission_for?(requested_action, :admin, :read, :category) },
98
+ -> { permission_for?(requested_action, :admin, :create, :category) },
99
+ -> { same_area_permission_for?(requested_action, :admin, :update, :category, restricted_rsrc: context[:category]&.participatory_space) },
100
+ -> { same_area_permission_for?(requested_action, :admin, :destroy, :category, restricted_rsrc: context[:category]&.participatory_space) },
101
+ # ATTACHMENT COLLECTIONS
102
+ -> { permission_for?(requested_action, :admin, :read, :attachment_collection) },
103
+ -> { permission_for?(requested_action, :admin, :create, :attachment_collection) },
104
+ -> { same_area_permission_for?(requested_action, :admin, :read, :attachment_collection, restricted_rsrc: context[:attachment_collection]&.collection_for) },
105
+ -> { same_area_permission_for?(requested_action, :admin, :update, :attachment_collection, restricted_rsrc: context[:attachment_collection]&.collection_for) },
106
+ -> { same_area_permission_for?(requested_action, :admin, :destroy, :attachment_collection, restricted_rsrc: context[:attachment_collection]&.collection_for) },
107
+ # ATTACHMENTS
108
+ -> { permission_for?(requested_action, :admin, :read, :attachment) },
109
+ -> { permission_for?(requested_action, :admin, :create, :attachment) },
110
+ -> { same_area_permission_for?(requested_action, :admin, :update, :attachment, restricted_rsrc: context[:attachment]&.attached_to) },
111
+ -> { same_area_permission_for?(requested_action, :admin, :destroy, :attachment, restricted_rsrc: context[:attachment]&.attached_to) },
112
+ # INVITE PROCESS ADMIN: USER ROLES
113
+ -> { permission_for?(requested_action, :admin, :read, :process_user_role) },
114
+ -> { permission_for?(requested_action, :admin, :create, :process_user_role) },
115
+ -> { permission_for?(requested_action, :admin, :update, :process_user_role) },
116
+ -> { permission_for?(requested_action, :admin, :destroy, :process_user_role) },
117
+ # SPACE PRIVATE USERS
118
+ -> { permission_for?(requested_action, :admin, :read, :space_private_user) },
119
+ -> { permission_for?(requested_action, :admin, :create, :space_private_user) },
120
+ -> { same_area_permission_for?(requested_action, :admin, :update, :space_private_user, restricted_rsrc: context[:private_user]&.privatable_to) },
121
+ -> { same_area_permission_for?(requested_action, :admin, :destroy, :space_private_user, restricted_rsrc: context[:private_user]&.privatable_to) },
122
+ -> { same_area_permission_for?(requested_action, :admin, :invite, :space_private_user, restricted_rsrc: context[:private_user]&.privatable_to) },
123
+ # MODERATIONS
124
+ -> { permission_for?(requested_action, :admin, :read, :moderation) },
125
+ -> { permission_for?(requested_action, :admin, :unreport, :moderation) },
126
+ -> { permission_for?(requested_action, :admin, :hide, :moderation) },
127
+ -> { permission_for?(requested_action, :admin, :unhide, :moderation) },
128
+
129
+ # ASSEMBLIES
130
+ -> { permission_for?(requested_action, :admin, :enter, :space_area, space_name: :assemblies) },
131
+ -> { permission_for?(requested_action, :admin, :read, :assembly_list) },
132
+ -> { permission_for?(requested_action, :admin, :create, :assembly) },
133
+ -> { same_area_permission_for?(requested_action, :admin, :update, :assembly, restricted_rsrc: context[:assembly]) },
134
+ -> { same_area_permission_for?(requested_action, :admin, :publish, :assembly, restricted_rsrc: context[:assembly]) },
135
+ -> { same_area_permission_for?(requested_action, :admin, :unpublish, :assembly, restricted_rsrc: context[:assembly]) },
136
+ -> { permission_for?(requested_action, :admin, :import, :assembly) },
137
+ # Assemly Admin: USER ROLES
138
+ -> { permission_for?(requested_action, :admin, :index, :assembly_user_role) },
139
+ -> { permission_for?(requested_action, :admin, :read, :assembly_user_role) },
140
+ -> { permission_for?(requested_action, :admin, :create, :assembly_user_role) },
141
+ -> { permission_for?(requested_action, :admin, :update, :assembly_user_role) },
142
+ -> { permission_for?(requested_action, :admin, :invite, :assembly_user_role) },
143
+ -> { permission_for?(requested_action, :admin, :destroy, :assembly_user_role) },
144
+
145
+ # Assembly Members
146
+ -> { same_area_permission_for?(requested_action, :admin, :read, :assembly_member, restricted_rsrc: context[:assembly]) },
147
+ -> { permission_for?(requested_action, :admin, :index, :assembly_member) },
148
+ -> { permission_for?(requested_action, :admin, :create, :assembly_member) },
149
+ -> { permission_for?(requested_action, :admin, :update, :assembly_member) },
150
+ -> { permission_for?(requested_action, :admin, :destroy, :assembly_member) },
151
+ # other assembly_member permissions are setted via Decidim::Assemblies::AssembliesWithUserRole decorator
152
+
153
+ # NEWSLETTER
154
+ -> { permission_for?(requested_action, :admin, :index, :newsletter) },
155
+ -> { permission_for?(requested_action, :admin, :read, :newsletter) },
156
+ -> { permission_for?(requested_action, :admin, :create, :newsletter) },
157
+ -> { same_area_permission_for?(requested_action, :admin, :update, :newsletter, restricted_rsrc: context[:newsletter]) },
158
+ -> { same_area_permission_for?(requested_action, :admin, :destroy, :newsletter, restricted_rsrc: context[:newsletter]) },
159
+
160
+ # CONFERENCES
161
+ -> { permission_for?(requested_action, :admin, :enter, :space_area, space_name: :conferences) },
162
+ -> { permission_for?(requested_action, :admin, :read, :conference_list) },
163
+ -> { permission_for?(requested_action, :admin, :create, :conference) },
164
+ -> { permission_for?(requested_action, :admin, :preview, :conference) },
165
+ -> { same_area_permission_for?(requested_action, :admin, :update, :conference, restricted_rsrc: context[:conference]) },
166
+ # Conference Admin: USER ROLES
167
+ -> { permission_for?(requested_action, :admin, :index, :conference_user_role) },
168
+ -> { permission_for?(requested_action, :admin, :read, :conference_user_role) },
169
+ -> { permission_for?(requested_action, :admin, :create, :conference_user_role) },
170
+ -> { permission_for?(requested_action, :admin, :update, :conference_user_role) },
171
+ -> { permission_for?(requested_action, :admin, :invite, :conference_user_role) },
172
+ -> { permission_for?(requested_action, :admin, :destroy, :conference_user_role) },
173
+
174
+ # USERS ADMINISTRATORS
175
+ -> { permission_for?(requested_action, :admin, :enter, :space_area, space_name: :users) },
176
+ -> { permission_for?(requested_action, :admin, :read, :admin_user) },
177
+ -> { permission_for?(requested_action, :admin, :create, :admin_user) },
178
+ -> { permission_for?(requested_action, :admin, :read, :managed_user) },
179
+ # USERS PARTICIPANTS
180
+ -> { permission_for?(requested_action, :admin, :index, :officialization) },
181
+ -> { permission_for?(requested_action, :admin, :read, :officialization) },
182
+ -> { permission_for?(requested_action, :admin, :create, :officialization) },
183
+ ]
184
+ default_checks.any?(&:call) || any_configurable_check?(requested_action)
185
+ end
186
+
187
+ def any_configurable_check?(requested_action)
188
+ configurable_checks.any? do |check|
189
+ check = check.entries.first
190
+ method = check.first
191
+ args = check.last
192
+ next unless [:permission_for?, :same_area_permission_for].include?(method)
193
+
194
+ send(method, requested_action, *args)
195
+ end
196
+ end
197
+
198
+ ALLOWED_SPACES = ["Decidim::ParticipatoryProcess", "Decidim::Assembly", "Decidim::Conference"].freeze
199
+ def permission_for_current_space?(permission_action)
200
+ has = permission_for?(permission_action, :admin, :read, :participatory_space)
201
+ has ||= permission_for?(permission_action, :public, :read, :participatory_space)
202
+ has &&= ALLOWED_SPACES.include?(context[:current_participatory_space].class.name)
203
+ has
204
+ end
205
+
206
+ # Does user have permission for the specified scope/action/subject?
207
+ def permission_for?(requested_action, scope, action, subject, expected_context = {})
208
+ same_action?(requested_action, scope, action, subject, expected_context)
209
+ end
210
+
211
+ # Does user have permission for the specified scope/action/subject?
212
+ # Also check if the resource in the context for with the key defined by `area_restricted_rsrc`
213
+ # has the same area as current user.
214
+ def same_area_permission_for?(requested_action, scope, action, subject, restricted_rsrc:)
215
+ if restricted_rsrc.respond_to?(:area) || restricted_rsrc.nil?
216
+ is = same_action?(requested_action, scope, action, subject)
217
+ is &&= in_same_area?(restricted_rsrc)
218
+ is
219
+ elsif restricted_rsrc.try(:participatory_space).try(:area).present?
220
+ same_area_permission_for?(requested_action, scope, action, subject, restricted_rsrc: restricted_rsrc.try(:participatory_space))
221
+ else
222
+ permission_for?(requested_action, scope, action, subject)
223
+ end
224
+ end
225
+
226
+ # Is current action requesting permissions for the specified scope/action/subject?
227
+ def same_action?(requested_action, scope, action, subject, expected_context = {})
228
+ is = requested_action.matches?(scope, action, subject)
229
+ expected_context.each_pair do |key, expected_value|
230
+ is &&= (context.try(:[], key) == expected_value)
231
+ end
232
+ is
233
+ end
234
+
235
+ def in_same_area?(resource)
236
+ user.areas.include? resource&.area
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module ParticipatoryProcesses
5
+ class ParticipatorySpacePermissions < Decidim::DepartmentAdmin::Permissions
6
+ def initialize(*)
7
+ # This are the same permissions as Decidim's processes space.
8
+ # Right now are the same for admin and public views
9
+ self.class.delegate_chain = [Decidim::ParticipatoryProcesses::Permissions]
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # A class used to filter users by processes that hey administer
6
+ class UserAdminBySpaceNameFilter < Decidim::Query
7
+ # termsc - text to filter users by
8
+ def self.for(term = nil, organization = nil, current_locale = :ca)
9
+ new(term, organization, current_locale).query
10
+ end
11
+
12
+ # Initializes the class.
13
+ #
14
+ # term - text to filter users by name or email
15
+ def initialize(term = nil, organization = nil, current_locale = :ca)
16
+ @term = term
17
+ @organization = organization
18
+ @current_locale = current_locale
19
+ super(Decidim::User.space_admins(@organization))
20
+ end
21
+
22
+ def query
23
+ filter_by_processes_term
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :term, :current_locale
29
+
30
+ def filter_by_processes_term
31
+ return @scope if term.blank?
32
+
33
+ containing_space_name = "%#{term}%"
34
+
35
+ query = <<-EOSQL
36
+ (id in (select decidim_user_id
37
+ from decidim_participatory_process_user_roles
38
+ where decidim_participatory_process_id in (
39
+ select id
40
+ from decidim_participatory_processes
41
+ where lower(title->>?) like lower(?)))
42
+ or id in ( select decidim_user_id
43
+ from decidim_assembly_user_roles
44
+ where decidim_assembly_id in (
45
+ select id
46
+ from decidim_assemblies
47
+ where lower(title->>?) like lower(?)))
48
+ #{if Decidim::DepartmentAdmin.conferences_defined?
49
+ "or id in ( select decidim_user_id
50
+ from decidim_conference_user_roles
51
+ where decidim_conference_id in (
52
+ select id
53
+ from decidim_conferences
54
+ where lower(title->>?) like lower(?))))" else
55
+ ")"
56
+ end}
57
+ EOSQL
58
+
59
+ if Decidim::DepartmentAdmin.conferences_defined?
60
+ @scope.where(query, current_locale, containing_space_name, current_locale, containing_space_name, current_locale, containing_space_name)
61
+ else
62
+ @scope.where(query, current_locale, containing_space_name, current_locale, containing_space_name)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # A class used to filter users by whitelisted scope or searches on their
6
+ # name
7
+ class UserAdminFilter < Decidim::Query
8
+ # scope - the ActiveRecord::Relation of users to be filtered
9
+ # termsc - text to filter users by
10
+ # role - evaluation role to be used as a filter
11
+ def self.for(scope, term = nil, role = nil, organization = nil)
12
+ new(scope, term, role, organization).query
13
+ end
14
+
15
+ # Initializes the class.
16
+ #
17
+ # scope - the ActiveRecord::Relation of users to be filtered
18
+ # term - text to filter users by name or email
19
+ # role - users role, must be defined as a scope in the user model
20
+ def initialize(scope, term = nil, role = nil, organization = nil)
21
+ @scope = scope
22
+ @term = term
23
+ @role = role
24
+ @organization = organization
25
+ super(scope)
26
+ end
27
+
28
+ def query
29
+ filter_by_role(scope)
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :term, :role, :scope
35
+
36
+ def filter_by_role(users)
37
+ case role
38
+ when "space_admin"
39
+ Decidim::User.space_admins(@organization)
40
+ when "admin"
41
+ users.where('"decidim_users"."admin" = ?', true)
42
+ when "department_admin", "user_manager"
43
+ users.where("? = any(roles)", role)
44
+ else
45
+ users.or(Decidim::User.space_admins(@organization))
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,32 @@
1
+ <% if controller_name == "users" %>
2
+ <div class='department-admin-filter filter row'>
3
+ <div>
4
+ <span class='dropdown-menu-inverted_label'><%= t('.filter_by') %> :</span>
5
+ <ul class="dropdown menu" data-dropdown-menu data-close-on-click-inside="false">
6
+ <li class='is-dropdown-submenu-parent'>
7
+ <a href='#'>
8
+ <% if @role.present? %>
9
+ <%= t("models.user.fields.roles.#{@role}", scope: 'decidim.admin') %>
10
+ <% else %>
11
+ <%= t('.filter.all') %>
12
+ <% end %>
13
+ </a>
14
+ <ul class='menu is-dropdown-submenu'>
15
+ <% Decidim::User::Roles.all.map do |role| %>
16
+ <li><%= link_to t("models.user.fields.roles.#{role}", scope: 'decidim.admin'), url_for(role: role, q: ransack_params) %></li>
17
+ <% end %>
18
+ <li><%= link_to t('models.user.fields.roles.space_admin', scope: 'decidim.admin'), url_for(role: 'space_admin', q: ransack_params) %></li>
19
+ <li><%= link_to t('.filter.all'), url_for(q: ransack_params) %></li>
20
+ </ul>
21
+ </li>
22
+ </ul>
23
+ <div class="process-or-admins">
24
+ <%= t('models.user.fields.search_question', scope: 'decidim.admin') %>
25
+ <input type='radio' id='processes_filter' name='filter_search' value='by_process_name' <%= @by_process_name ? "checked" : "" %> style='margin-left: 20px'>
26
+ <label for='processes_filter'><%= t('models.user.fields.search_field_processes', scope: 'decidim.admin') %></label>
27
+ <input type='radio' id='query_filter' name='filter_search' value='query' <%= params[:filter_search].blank? || params[:filter_search] == "query" ? "checked" : "" %> >
28
+ <label for='query_filter'><%= t('models.user.fields.search_field_admins', scope: 'decidim.admin') %></label>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ <% end %>
@@ -0,0 +1,36 @@
1
+ <div class="form__wrapper">
2
+ <div class="card pt-4">
3
+ <div class="card-section">
4
+ <div class="row column">
5
+ <%= form.text_field :name, label: t(".name") %>
6
+ </div>
7
+
8
+ <div class="row column">
9
+ <%= form.email_field :email, label: t(".email") %>
10
+ </div>
11
+
12
+ <div class="row column">
13
+ <%= form.select :role, @form.available_roles_for_select, label: t(".role") %>
14
+ </div>
15
+
16
+ <div id="area-block" class="row column">
17
+ <%= form.select :area_id,
18
+ @form.available_areas_for_select,
19
+ { label: t(".area") },
20
+ { disabled: current_user.roles.include?('department_admin') }
21
+ %>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </div>
26
+
27
+ <%= javascript_tag do %>
28
+ $('#user_role').on('change', function(ev) {
29
+ var opt= ev.target
30
+ if(opt.value == 'department_admin') {
31
+ $('#area-block').show()
32
+ } else {
33
+ $('#area-block').hide()
34
+ }
35
+ })
36
+ <% end -%>