decidim-core 0.27.4 → 0.27.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/activity_cell.rb +2 -2
  3. data/app/cells/decidim/card_cell.rb +2 -2
  4. data/app/cells/decidim/card_m/top.erb +1 -1
  5. data/app/cells/decidim/card_m_cell.rb +1 -1
  6. data/app/cells/decidim/scopes_picker/scope_picker_values.erb +1 -1
  7. data/app/cells/decidim/tags_cell.rb +3 -1
  8. data/app/cells/decidim/upload_modal/modal.erb +4 -1
  9. data/app/cells/decidim/upload_modal_cell.rb +8 -4
  10. data/app/cells/decidim/user_profile_cell.rb +1 -1
  11. data/app/cells/decidim/version_cell.rb +1 -1
  12. data/app/cells/decidim/versions_list_cell.rb +1 -1
  13. data/app/commands/decidim/create_omniauth_registration.rb +2 -4
  14. data/app/commands/decidim/endorse_resource.rb +2 -0
  15. data/app/commands/decidim/messaging/reply_to_conversation.rb +3 -0
  16. data/app/commands/decidim/messaging/start_conversation.rb +3 -0
  17. data/app/commands/decidim/search.rb +1 -1
  18. data/app/commands/decidim/unendorse_resource.rb +1 -1
  19. data/app/controllers/concerns/decidim/devise_authentication_methods.rb +36 -0
  20. data/app/controllers/concerns/decidim/force_authentication.rb +6 -2
  21. data/app/controllers/concerns/decidim/paginable.rb +1 -1
  22. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +1 -22
  23. data/app/controllers/decidim/devise/registrations_controller.rb +1 -1
  24. data/app/controllers/decidim/devise/sessions_controller.rb +1 -24
  25. data/app/controllers/decidim/links_controller.rb +1 -1
  26. data/app/controllers/decidim/searches_controller.rb +1 -1
  27. data/app/controllers/decidim/user_timeline_controller.rb +1 -1
  28. data/app/controllers/decidim/widgets_controller.rb +6 -0
  29. data/app/events/decidim/welcome_notification_event.rb +6 -9
  30. data/app/forms/decidim/account_form.rb +1 -1
  31. data/app/forms/decidim/notifications_settings_form.rb +0 -8
  32. data/app/forms/decidim/registration_form.rb +1 -1
  33. data/app/helpers/decidim/cells_paginate_helper.rb +1 -1
  34. data/app/helpers/decidim/check_boxes_tree_helper.rb +4 -4
  35. data/app/helpers/decidim/decidim_form_helper.rb +1 -0
  36. data/app/helpers/decidim/newsletters_helper.rb +83 -16
  37. data/app/helpers/decidim/omniauth_helper.rb +2 -0
  38. data/app/helpers/decidim/resource_helper.rb +3 -1
  39. data/app/helpers/decidim/sanitize_helper.rb +9 -0
  40. data/app/helpers/decidim/short_link_helper.rb +1 -1
  41. data/app/helpers/decidim/user_profile_helper.rb +7 -2
  42. data/app/jobs/decidim/download_your_data_export_job.rb +2 -1
  43. data/app/jobs/decidim/open_data_job.rb +2 -0
  44. data/app/mailers/decidim/messaging/conversation_mailer.rb +3 -72
  45. data/app/models/decidim/push_notification_message.rb +39 -0
  46. data/app/models/decidim/user.rb +9 -1
  47. data/app/packs/images/decidim/icons.svg +1 -1
  48. data/app/packs/images/decidim/vendor/social-share-button/x.svg +6 -0
  49. data/app/packs/src/decidim/autocomplete.js +11 -2
  50. data/app/packs/src/decidim/data_picker.js +1 -0
  51. data/app/packs/src/decidim/direct_uploads/upload_field.js +6 -4
  52. data/app/packs/src/decidim/direct_uploads/upload_modal.js +10 -8
  53. data/app/packs/src/decidim/direct_uploads/uploader.js +4 -1
  54. data/app/packs/src/decidim/geocoding/attach_input.js +4 -1
  55. data/app/packs/src/decidim/geocoding/provider/here.js +17 -21
  56. data/app/packs/src/decidim/geocoding/provider/photon.js +1 -1
  57. data/app/packs/src/decidim/input_hashtags.js +1 -1
  58. data/app/packs/src/decidim/input_mentions.js +1 -1
  59. data/app/packs/src/decidim/input_multiple_mentions.js +1 -1
  60. data/app/packs/src/decidim/utilities/text.js +17 -0
  61. data/app/packs/src/decidim/vizzs/index.js +1 -1
  62. data/app/packs/stylesheets/decidim/_variables.scss +1 -1
  63. data/app/packs/stylesheets/decidim/plugins/leaflet.scss +118 -114
  64. data/app/packs/stylesheets/decidim/vendor/_social_share_button.scss +4 -0
  65. data/app/presenters/decidim/admin_log/oauth_application_resource_presenter.rb +1 -1
  66. data/app/presenters/decidim/notification_to_mailer_presenter.rb +9 -0
  67. data/app/services/decidim/events_manager.rb +6 -0
  68. data/app/services/decidim/push_notification_message_sender.rb +36 -0
  69. data/app/services/decidim/send_push_notification.rb +22 -8
  70. data/app/views/decidim/devise/registrations/new.html.erb +2 -2
  71. data/app/views/decidim/notifications_digest_mailer/_email_content.html.erb +7 -0
  72. data/app/views/decidim/notifications_settings/show.html.erb +1 -1
  73. data/app/views/decidim/scopes/_scopes_picker_input.html.erb +1 -1
  74. data/app/views/decidim/searches/_filters.html.erb +3 -1
  75. data/app/views/decidim/shared/_address_details.html.erb +2 -2
  76. data/app/views/decidim/shared/_share_modal.html.erb +1 -1
  77. data/app/views/decidim/shared/participatory_space_filters/_filters.html.erb +1 -1
  78. data/app/views/layouts/decidim/_js_configuration.html.erb +1 -0
  79. data/app/views/layouts/decidim/_social_media_links.html.erb +2 -2
  80. data/config/locales/ar.yml +12 -16
  81. data/config/locales/bg.yml +77 -15
  82. data/config/locales/ca.yml +34 -30
  83. data/config/locales/cs.yml +18 -14
  84. data/config/locales/de.yml +62 -58
  85. data/config/locales/el.yml +11 -16
  86. data/config/locales/en.yml +5 -1
  87. data/config/locales/eo.yml +2 -3
  88. data/config/locales/es-MX.yml +15 -11
  89. data/config/locales/es-PY.yml +15 -11
  90. data/config/locales/es.yml +30 -26
  91. data/config/locales/eu.yml +500 -342
  92. data/config/locales/fi-plain.yml +7 -3
  93. data/config/locales/fi.yml +21 -17
  94. data/config/locales/fr-CA.yml +17 -13
  95. data/config/locales/fr.yml +12 -8
  96. data/config/locales/ga-IE.yml +5 -5
  97. data/config/locales/gl.yml +5 -19
  98. data/config/locales/he-IL.yml +1 -0
  99. data/config/locales/hu.yml +63 -23
  100. data/config/locales/id-ID.yml +4 -19
  101. data/config/locales/is-IS.yml +4 -2
  102. data/config/locales/it.yml +15 -17
  103. data/config/locales/ja.yml +26 -22
  104. data/config/locales/lb.yml +15 -17
  105. data/config/locales/lt.yml +55 -10
  106. data/config/locales/lv.yml +4 -16
  107. data/config/locales/nl.yml +12 -12
  108. data/config/locales/no.yml +8 -10
  109. data/config/locales/pl.yml +151 -1
  110. data/config/locales/pt-BR.yml +267 -22
  111. data/config/locales/pt.yml +8 -10
  112. data/config/locales/ro-RO.yml +4 -10
  113. data/config/locales/ru.yml +13 -17
  114. data/config/locales/sk.yml +7 -17
  115. data/config/locales/sl.yml +0 -5
  116. data/config/locales/sq-AL.yml +1 -0
  117. data/config/locales/sv.yml +55 -17
  118. data/config/locales/th-TH.yml +1 -0
  119. data/config/locales/tr-TR.yml +18 -15
  120. data/config/locales/uk.yml +17 -14
  121. data/config/locales/zh-CN.yml +6 -10
  122. data/config/locales/zh-TW.yml +0 -9
  123. data/db/migrate/20231027142329_change_default_value_for_decidim_endorsements.rb +11 -0
  124. data/db/seeds.rb +1 -0
  125. data/decidim-core.gemspec +78 -0
  126. data/lib/decidim/acts_as_tree.rb +14 -1
  127. data/lib/decidim/asset_router/storage.rb +4 -0
  128. data/lib/decidim/attribute_encryptor.rb +6 -4
  129. data/lib/decidim/core/engine.rb +7 -3
  130. data/lib/decidim/core/test/factories.rb +309 -95
  131. data/lib/decidim/core/test/shared_examples/amendable/amendment_created_event_examples.rb +6 -26
  132. data/lib/decidim/core/test/shared_examples/amendable/amendment_promoted_event_examples.rb +8 -26
  133. data/lib/decidim/core/test/shared_examples/comments_examples.rb +56 -0
  134. data/lib/decidim/core/test/shared_examples/embed_resource_examples.rb +187 -11
  135. data/lib/decidim/core/test/shared_examples/errors.rb +2 -0
  136. data/lib/decidim/core/test/shared_examples/has_attachment_collections.rb +8 -6
  137. data/lib/decidim/core/test/shared_examples/has_attachments.rb +4 -4
  138. data/lib/decidim/core/test/shared_examples/has_category.rb +27 -0
  139. data/lib/decidim/core/test/shared_examples/has_reference.rb +1 -1
  140. data/lib/decidim/core/test/shared_examples/has_space_in_mcell_examples.rb +1 -2
  141. data/lib/decidim/core/test/shared_examples/resource_endorsed_event_examples.rb +6 -3
  142. data/lib/decidim/core/test/shared_examples/resource_locator_presenter_examples.rb +134 -0
  143. data/lib/decidim/core/test/shared_examples/searchable_results_examples.rb +1 -1
  144. data/lib/decidim/core/test/shared_examples/simple_event.rb +50 -2
  145. data/lib/decidim/core/test.rb +1 -0
  146. data/lib/decidim/core/version.rb +1 -1
  147. data/lib/decidim/core.rb +2 -1
  148. data/lib/decidim/endorsable.rb +1 -1
  149. data/lib/decidim/engine_router.rb +17 -4
  150. data/lib/decidim/events/base_event.rb +5 -2
  151. data/lib/decidim/events/simple_event.rb +3 -17
  152. data/lib/decidim/exporters.rb +10 -1
  153. data/lib/decidim/form_builder.rb +1 -0
  154. data/lib/decidim/has_category.rb +3 -3
  155. data/lib/decidim/has_conversations.rb +91 -0
  156. data/lib/decidim/participable.rb +17 -0
  157. data/lib/decidim/view_model.rb +1 -0
  158. data/lib/decidim/webpacker/webpack/.modernizrrc +9 -0
  159. data/lib/premailer/adapter/decidim.rb +5 -4
  160. data/lib/tasks/decidim_reminders_tasks.rake +1 -0
  161. data/lib/tasks/upgrade/decidim_deduplicate_endorsements.rake +53 -0
  162. data/lib/tasks/upgrade/decidim_fix_categorization.rake +15 -0
  163. data/lib/tasks/upgrade/decidim_fix_short_url_resolver.rake +22 -0
  164. metadata +37 -32
  165. data/app/helpers/decidim/layout_helper.rb.orig +0 -225
  166. data/app/packs/stylesheets/decidim/modules/_dropdown_menu.scss +0 -9
  167. data/app/views/decidim/devise/registrations/new.html.erb.orig +0 -231
  168. /data/{config/environment.rb → app/packs/images/decidim/.keep} +0 -0
@@ -8,28 +8,28 @@ module Decidim
8
8
  # for example transform "https://es.lipsum.com/" to "https://es.lipsum.com/?utm_source=localhost&utm_campaign=newsletter_11"
9
9
  # And replace "%{name}" on the subject or content of newsletter to the user Name
10
10
  # for example transform "%{name}" to "User Name"
11
+ #
12
+ # @param content [String] - the string to convert
13
+ # @param user [Decidim::User] - the user to replace
14
+ # @param id [Integer] - the id of the newsletter to change
15
+ #
16
+ # @return [String] - the content converted
11
17
  def parse_interpolations(content, user = nil, id = nil)
12
- if Decidim.config.track_newsletter_links && id.present? && user.present?
13
- host = user.organization.host.to_s
14
- campaign = "newsletter_#{id}"
18
+ host = user&.organization&.host&.to_s
15
19
 
16
- links = content.scan(/href\s*=\s*"([^"]*)"/)
17
-
18
- links.each do |link|
19
- link_replaced = link.first + utm_codes(host, campaign)
20
- content = content.gsub(/href\s*=\s*"([^"]*#{link.first})"/, %(href="#{link_replaced}"))
21
- end
22
- end
23
-
24
- if user.present?
25
- content.gsub("%{name}", user.name)
26
- else
27
- content.gsub("%{name}", "")
28
- end
20
+ content = interpret_name(content, user)
21
+ content = track_newsletter_links(content, id, host)
22
+ transform_image_urls(content, host)
29
23
  end
30
24
 
31
25
  # this method is used to generate the root link on mail with the utm_codes
32
26
  # If the newsletter_id is nil, it returns the root_url
27
+ #
28
+ # @param organization [Decidim::Organization] - the Organization of this newsletter
29
+ # @param newsletter_id [Integer] - the id of the newsletter
30
+ #
31
+ # @return [String] - the root_url converted
32
+ #
33
33
  def custom_url_for_mail_root(organization, newsletter_id = nil)
34
34
  decidim = EngineRouter.new("decidim", {})
35
35
  if newsletter_id.present?
@@ -39,10 +39,77 @@ module Decidim
39
39
  end
40
40
  end
41
41
 
42
+ private
43
+
42
44
  # Method to specify the utm_codes.
43
45
  # You can change or add utm_codes for track
46
+ #
47
+ # @param host [String] - the Decidim::Organization host add to the URL
48
+ # @param newsletter_id [String] - the ID of the newsletter
49
+ #
50
+ # @return [String] - the UTM codes to be added
51
+ #
44
52
  def utm_codes(host, newsletter_id)
45
53
  "?utm_source=#{host}&utm_campaign=#{newsletter_id}"
46
54
  end
55
+
56
+ # Interpret placeholder '%{name}' and replace by the user name
57
+ # If user is not define, it returns content with blank instead of the placeholder
58
+ #
59
+ # @param content [String] - the string to convert
60
+ # @param user [Decidim::User] - the user to replace
61
+ #
62
+ # @return [String] - the content converted
63
+ #
64
+ def interpret_name(content, user)
65
+ return content.gsub("%{name}", "") if user.blank?
66
+
67
+ content.gsub("%{name}", user.name)
68
+ end
69
+
70
+ # Find each img HTML tag with relative path in src attribute
71
+ # For each URL, prepends the decidim.root_url
72
+ # If host is not defined it returns full content
73
+ #
74
+ # @param content [String] - the string to convert
75
+ # @param host [String] - the Decidim::Organization host to replace
76
+ #
77
+ # @return [String] - the content converted
78
+ #
79
+ def transform_image_urls(content, host)
80
+ return content if host.blank?
81
+
82
+ content.scan(/src\s*=\s*"([^"]*)"/).each do |src|
83
+ root_url = decidim.root_url(host: host)[0..-2]
84
+ src_replaced = "#{root_url}#{src.first}"
85
+ content = content.gsub(/src\s*=\s*"([^"]*#{src.first})"/, %(src="#{src_replaced}"))
86
+ end
87
+
88
+ content
89
+ end
90
+
91
+ # Add tracking query params to each links
92
+ #
93
+ # @param content [String] - the string to convert
94
+ # @param id [Integer] - the id of the newsletter
95
+ # @param host [String] - the Decidim::Organization host
96
+ #
97
+ # @return [String] - the content converted
98
+ #
99
+ def track_newsletter_links(content, id, host)
100
+ return content unless Decidim.config.track_newsletter_links
101
+ return content if id.blank?
102
+ return content if host.blank?
103
+
104
+ campaign = "newsletter_#{id}"
105
+ links = content.scan(/href\s*=\s*"([^"]*)"/)
106
+
107
+ links.each do |link|
108
+ link_replaced = link.first + utm_codes(host, campaign)
109
+ content = content.gsub(/href\s*=\s*"([^"]*#{link.first})"/, %(href="#{link_replaced}"))
110
+ end
111
+
112
+ content
113
+ end
47
114
  end
48
115
  end
@@ -6,6 +6,8 @@ module Decidim
6
6
  # Public: normalize providers names to they can be used for buttons
7
7
  # and icons.
8
8
  def normalize_provider_name(provider)
9
+ return "x" if provider == :twitter
10
+
9
11
  provider.to_s.split("_").first
10
12
  end
11
13
 
@@ -67,13 +67,15 @@ module Decidim
67
67
 
68
68
  # Returns an instance of ResourceLocatorPresenter with the given resource
69
69
  def resource_locator(resource)
70
+ return resource.resource_locator if resource.respond_to?(:resource_locator)
71
+
70
72
  ::Decidim::ResourceLocatorPresenter.new(resource)
71
73
  end
72
74
 
73
75
  # Returns a descriptive title for the resource
74
76
  def resource_title(resource)
75
77
  title = resource.try(:title) || resource.try(:name) || resource.try(:subject) || "#{resource.model_name.human} ##{resource.id}"
76
- title = translated_attribute(title) if title.is_a?(Hash)
78
+ title = decidim_escape_translated(title) if title.is_a?(Hash)
77
79
  title
78
80
  end
79
81
  end
@@ -6,6 +6,7 @@ module Decidim
6
6
  def self.included(base)
7
7
  base.include ActionView::Helpers::SanitizeHelper
8
8
  base.include ActionView::Helpers::TagHelper
9
+ base.include Decidim::TranslatableAttributes
9
10
  end
10
11
 
11
12
  # Public: It sanitizes a user-inputted string with the
@@ -53,6 +54,14 @@ module Decidim
53
54
  decidim_html_escape(text).sub(/^javascript:/, "")
54
55
  end
55
56
 
57
+ def decidim_sanitize_translated(text)
58
+ decidim_sanitize(translated_attribute(text))
59
+ end
60
+
61
+ def decidim_escape_translated(text)
62
+ decidim_html_escape(translated_attribute(text))
63
+ end
64
+
56
65
  private
57
66
 
58
67
  # Maintains the paragraphs and lists separations with their bullet points and
@@ -21,7 +21,7 @@ module Decidim
21
21
  target ||= respond_to?(:current_organization) && current_organization
22
22
  target ||= Rails.application
23
23
 
24
- mounted_engine = EngineResolver.new(_routes).mounted_name
24
+ mounted_engine = target.try(:mounted_engine) || EngineResolver.new(_routes).mounted_name
25
25
  ShortLink.to(target, mounted_engine, **kwargs).short_url
26
26
  end
27
27
  end
@@ -14,9 +14,14 @@ module Decidim
14
14
  #
15
15
  # Returns a String with the menu tab.
16
16
  def user_profile_tab(text, link, options = {})
17
- active = is_active_link?(link, (options[:aria_link_type] || :inclusive))
17
+ aria = {}
18
+ cls = %w(tabs-title)
19
+ if is_active_link?(link, (options[:aria_link_type] || :inclusive))
20
+ cls << "is-active"
21
+ aria[:current] = "page"
22
+ end
18
23
 
19
- content_tag(:li, class: "tabs-title#{active ? " is-active" : nil}") do
24
+ content_tag(:li, class: cls.join(" "), aria: aria) do
20
25
  link_to(text, link, options)
21
26
  end
22
27
  end
@@ -11,7 +11,8 @@ module Decidim
11
11
 
12
12
  generate_zip_file(user, path, password, export_format)
13
13
  save_or_upload_file(user, path)
14
-
14
+ # Deletes temporary file
15
+ File.delete(path)
15
16
  ExportMailer.download_your_data_export(user, filename, password).deliver_later
16
17
  end
17
18
 
@@ -11,6 +11,8 @@ module Decidim
11
11
  raise "Couldn't generate Open Data export" unless exporter.export.positive?
12
12
 
13
13
  organization.open_data_file.attach(io: File.open(path, "rb"), filename: organization.open_data_file_path)
14
+ # Deletes the temporary file file
15
+ File.delete(path)
14
16
  end
15
17
  end
16
18
  end
@@ -5,74 +5,12 @@ module Decidim
5
5
  # A custom mailer for sending notifications to users when they receive
6
6
  # private messages
7
7
  class ConversationMailer < Decidim::ApplicationMailer
8
- def new_conversation(originator, user, conversation)
9
- notification_mail(
10
- from: originator,
11
- to: user,
12
- conversation: conversation,
13
- message: conversation.messages.first.body,
14
- action: "new_conversation"
15
- )
16
- end
17
-
18
- def new_group_conversation(originator, manager, conversation, group)
19
- notification_mail(
20
- from: originator,
21
- to: manager,
22
- conversation: conversation,
23
- message: conversation.messages.first.body,
24
- action: "new_group_conversation",
25
- third_party: group
26
- )
27
- end
28
-
29
- def comanagers_new_conversation(group, user, conversation, manager)
30
- notification_mail(
31
- from: group,
32
- to: user,
33
- conversation: conversation,
34
- message: conversation.messages.first.body,
35
- action: "comanagers_new_conversation",
36
- third_party: manager
37
- )
38
- end
39
-
40
- def new_message(sender, user, conversation, message)
41
- notification_mail(
42
- from: sender,
43
- to: user,
44
- conversation: conversation,
45
- message: message.body,
46
- action: "new_message"
47
- )
48
- end
49
-
50
- def new_group_message(sender, user, conversation, message, group)
51
- notification_mail(
52
- from: sender,
53
- to: user,
54
- conversation: conversation,
55
- message: message.body,
56
- action: "new_group_message",
57
- third_party: group
58
- )
59
- end
60
-
61
- def comanagers_new_message(sender, user, conversation, message, manager)
62
- notification_mail(
63
- from: sender,
64
- to: user,
65
- conversation: conversation,
66
- message: message.body,
67
- action: "comanagers_new_message",
68
- third_party: manager
69
- )
70
- end
8
+ include HasConversations
71
9
 
72
10
  private
73
11
 
74
12
  # rubocop:disable Metrics/ParameterLists
75
- def notification_mail(from:, to:, conversation:, action:, message: nil, third_party: nil)
13
+ def send_notification(from:, to:, conversation:, action:, message: nil, third_party: nil)
76
14
  with_user(to) do
77
15
  @organization = to.organization
78
16
  @conversation = conversation
@@ -81,14 +19,7 @@ module Decidim
81
19
  @third_party = third_party
82
20
  @message = message
83
21
  @host = @organization.host
84
-
85
- subject = I18n.t(
86
- "conversation_mailer.#{action}.subject",
87
- scope: "decidim.messaging",
88
- sender: @sender.name,
89
- manager: @third_party&.name,
90
- group: @third_party&.name
91
- )
22
+ subject = get_subject(action: action, sender: @sender, third_party: @third_party)
92
23
 
93
24
  mail(to: to.email, subject: subject)
94
25
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # A messsage from a conversation that will be sent as a push notification
5
+ class PushNotificationMessage
6
+ class InvalidActionError < StandardError; end
7
+
8
+ include SanitizeHelper
9
+ include Decidim::TranslatableAttributes
10
+
11
+ def initialize(recipient:, conversation:, message:)
12
+ @recipient = recipient
13
+ @conversation = conversation
14
+ @message = message
15
+ end
16
+
17
+ attr_reader :recipient, :conversation, :message
18
+
19
+ alias user recipient
20
+
21
+ def body
22
+ decidim_html_escape(translated_attribute(message))
23
+ end
24
+
25
+ def icon
26
+ organization.attached_uploader(:favicon).variant_url(:big, host: organization.host)
27
+ end
28
+
29
+ def url
30
+ EngineRouter.new("decidim", {}).public_send(:conversation_path, host: organization.host, id: @conversation)
31
+ end
32
+
33
+ private
34
+
35
+ def organization
36
+ @organization ||= recipient.organization
37
+ end
38
+ end
39
+ end
@@ -205,7 +205,7 @@ module Decidim
205
205
  end
206
206
 
207
207
  def admin_terms_accepted?
208
- return true if admin_terms_accepted_at
208
+ admin_terms_accepted_at.present?
209
209
  end
210
210
 
211
211
  # Whether this user can be verified against some authorization or not.
@@ -269,6 +269,14 @@ module Decidim
269
269
  password_updated_at < Decidim.config.admin_password_expiration_days.days.ago
270
270
  end
271
271
 
272
+ def moderator?
273
+ Decidim.participatory_space_manifests.map do |manifest|
274
+ participatory_space_type = manifest.model_class_name.constantize
275
+ return true if participatory_space_type.moderators(organization).exists?(id: id)
276
+ end
277
+ false
278
+ end
279
+
272
280
  protected
273
281
 
274
282
  # Overrides devise email required validation.