decidim-core 0.26.4 → 0.26.7

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/announcement_cell.rb +1 -1
  3. data/app/cells/decidim/content_blocks/cta_cell.rb +1 -1
  4. data/app/cells/decidim/content_blocks/hero/show.erb +1 -1
  5. data/app/cells/decidim/content_blocks/highlighted_content_banner/show.erb +1 -1
  6. data/app/cells/decidim/content_blocks/sub_hero_cell.rb +1 -1
  7. data/app/cells/decidim/newsletter_templates/base_cell.rb +8 -0
  8. data/app/cells/decidim/newsletter_templates/basic_only_text/show.erb +4 -4
  9. data/app/cells/decidim/newsletter_templates/image_text_cta/show.erb +4 -4
  10. data/app/commands/decidim/unendorse_resource.rb +1 -1
  11. data/app/controllers/decidim/groups_controller.rb +5 -0
  12. data/app/controllers/decidim/links_controller.rb +10 -11
  13. data/app/controllers/decidim/profiles_controller.rb +1 -1
  14. data/app/helpers/decidim/cells_helper.rb +1 -0
  15. data/app/helpers/decidim/external_domain_helper.rb +14 -3
  16. data/app/helpers/decidim/icon_helper.rb +3 -3
  17. data/app/helpers/decidim/newsletters_helper.rb +1 -0
  18. data/app/helpers/decidim/sanitize_helper.rb +15 -5
  19. data/app/mailers/decidim/newsletter_mailer.rb +10 -3
  20. data/app/models/decidim/newsletter.rb +28 -0
  21. data/app/models/decidim/scope_type.rb +28 -0
  22. data/app/models/decidim/user.rb +0 -2
  23. data/app/models/decidim/user_base_entity.rb +2 -0
  24. data/app/models/decidim/user_block.rb +2 -2
  25. data/app/models/decidim/user_group.rb +1 -1
  26. data/app/packs/src/decidim/editor/clipboard_override.js +6 -2
  27. data/app/packs/src/decidim/editor.js +63 -33
  28. data/app/packs/src/decidim/form_filter.component.test.js +148 -5
  29. data/app/packs/src/decidim/form_filter.js +26 -4
  30. data/app/packs/stylesheets/decidim/_editor.scss +129 -0
  31. data/app/packs/stylesheets/decidim/email.scss +7 -0
  32. data/app/packs/stylesheets/decidim/extras/_quill.scss +0 -6
  33. data/app/packs/stylesheets/decidim/modules/_buttons.scss +10 -6
  34. data/app/packs/stylesheets/decidim/modules/_cards.scss +1 -1
  35. data/app/packs/stylesheets/decidim/modules/_comments.scss +24 -0
  36. data/app/packs/stylesheets/decidim/vizzs/_linechart.scss +2 -2
  37. data/app/packs/stylesheets/decidim/vizzs/_rowchart.scss +2 -2
  38. data/app/presenters/decidim/admin_log/user_group_presenter.rb +1 -1
  39. data/app/presenters/decidim/admin_log/user_moderation_presenter.rb +1 -1
  40. data/app/presenters/decidim/notification_presenter.rb +1 -1
  41. data/app/presenters/decidim/user_group_presenter.rb +1 -1
  42. data/app/presenters/decidim/user_presenter.rb +1 -1
  43. data/app/scrubbers/decidim/admin_input_scrubber.rb +27 -0
  44. data/app/scrubbers/decidim/user_input_scrubber.rb +32 -5
  45. data/app/services/decidim/traceability.rb +1 -0
  46. data/app/views/decidim/links/_invalid_url_modal.html.erb +17 -0
  47. data/app/views/decidim/links/_modal.html.erb +1 -1
  48. data/app/views/decidim/links/invalid_url.js.erb +24 -0
  49. data/app/views/decidim/links/new.html.erb +1 -1
  50. data/app/views/decidim/messaging/conversations/_conversation.html.erb +1 -5
  51. data/app/views/decidim/newsletter_mailer/newsletter.html.erb +3 -3
  52. data/app/views/decidim/newsletters/show.html.erb +1 -1
  53. data/app/views/decidim/pages/_standalone.html.erb +1 -1
  54. data/app/views/decidim/pages/_tabbed.html.erb +1 -1
  55. data/app/views/layouts/decidim/_mailer_logo.html.erb +2 -2
  56. data/app/views/layouts/decidim/newsletter_base.html.erb +2 -2
  57. data/config/locales/ar.yml +427 -11
  58. data/config/locales/bg.yml +6 -8
  59. data/config/locales/ca.yml +36 -30
  60. data/config/locales/cs.yml +27 -32
  61. data/config/locales/da.yml +3 -0
  62. data/config/locales/de.yml +4 -26
  63. data/config/locales/el.yml +6 -9
  64. data/config/locales/en.yml +21 -15
  65. data/config/locales/eo.yml +2 -1
  66. data/config/locales/es-MX.yml +28 -22
  67. data/config/locales/es-PY.yml +28 -22
  68. data/config/locales/es.yml +34 -28
  69. data/config/locales/et.yml +3 -0
  70. data/config/locales/eu.yml +108 -85
  71. data/config/locales/fa-IR.yml +1 -0
  72. data/config/locales/fi-plain.yml +6 -21
  73. data/config/locales/fi.yml +24 -18
  74. data/config/locales/fr-CA.yml +26 -20
  75. data/config/locales/fr.yml +24 -18
  76. data/config/locales/ga-IE.yml +1 -0
  77. data/config/locales/gl.yml +2 -26
  78. data/config/locales/gn-PY.yml +3 -0
  79. data/config/locales/hr.yml +3 -0
  80. data/config/locales/hu.yml +52 -29
  81. data/config/locales/id-ID.yml +7 -8
  82. data/config/locales/is-IS.yml +2 -2
  83. data/config/locales/it.yml +2 -16
  84. data/config/locales/ja.yml +29 -39
  85. data/config/locales/ka-GE.yml +4 -0
  86. data/config/locales/kaa.yml +1 -0
  87. data/config/locales/lb.yml +0 -8
  88. data/config/locales/lt.yml +0 -37
  89. data/config/locales/lv.yml +5 -7
  90. data/config/locales/nl.yml +1 -24
  91. data/config/locales/no.yml +3 -30
  92. data/config/locales/oc-FR.yml +2 -0
  93. data/config/locales/pl.yml +2 -38
  94. data/config/locales/pt-BR.yml +2 -10
  95. data/config/locales/pt.yml +0 -8
  96. data/config/locales/ro-RO.yml +10 -11
  97. data/config/locales/ru.yml +6 -4
  98. data/config/locales/sk.yml +8 -9
  99. data/config/locales/sl.yml +1 -0
  100. data/config/locales/sr-CS.yml +2 -0
  101. data/config/locales/sv.yml +3 -29
  102. data/config/locales/tr-TR.yml +7 -12
  103. data/config/locales/uk.yml +6 -4
  104. data/config/locales/zh-CN.yml +3 -8
  105. data/config/locales/zh-TW.yml +1712 -0
  106. data/lib/decidim/api/types/localized_string_type.rb +9 -0
  107. data/lib/decidim/api/types/translated_field_type.rb +20 -5
  108. data/lib/decidim/core/test/factories.rb +13 -6
  109. data/lib/decidim/core/test/shared_examples/comments_examples.rb +36 -0
  110. data/lib/decidim/core/test/shared_examples/editor_shared_examples.rb +10 -0
  111. data/lib/decidim/core/test/shared_examples/rich_text_editor_examples.rb +7 -3
  112. data/lib/decidim/core/test.rb +1 -0
  113. data/lib/decidim/core/version.rb +1 -1
  114. data/lib/decidim/form_builder.rb +1 -2
  115. data/lib/decidim/participatory_space_resourceable.rb +7 -1
  116. data/lib/decidim/publicable.rb +4 -0
  117. metadata +13 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1863adec9ae8ce9d4d528f247a2f18561de3618eacb84e50c03fae6a89fb2d6e
4
- data.tar.gz: 032b9cce96757af5e5d87d687f64231a1630fdc003973b3b16cc4044f7f667bb
3
+ metadata.gz: 2d573b856227ec581d40d90cff9a85c1f21502a1ed6278b82aa9768a434f0e9c
4
+ data.tar.gz: 2ca2fff70b6e6b9314450c35ab22965b3ba60af303a2839c7716e502cb566b3a
5
5
  SHA512:
6
- metadata.gz: 44579a2195e6d79ca6e5d78a1695815c4db2d2dd850b9a94e819d5219cda61cad771aa172ad99628bb9460e79a99b02fa4cd72fb377649b565b22ad010eb6924
7
- data.tar.gz: 959d4d1552af3fd6b25fb1fb27292d8d107c260bedddd5a49dce829f6271772fd8a2c043d401cdc5061a615e1de71157d0b084eeab3b794e9aa3373451ad7ef8
6
+ metadata.gz: 1000d09afe7e9af0586fa14c917c77a150bf9f55adee9d0a243744799a9cf9c84aa364b0f014cdec6eda3855c10b4b15772732c979d9f15e381c8a62e78aad8f
7
+ data.tar.gz: 1a4feafaa713a4fa540aab815e0306f125cc74d45599d5defbec2e9dd2cce8bc6223acd0148424b3973a0f1d6853b96cd3ee9a6fda7ff45cc91073fd2b84ac8a
@@ -62,7 +62,7 @@ module Decidim
62
62
  end
63
63
 
64
64
  def clean(value)
65
- decidim_sanitize(translated_attribute(value))
65
+ decidim_sanitize_admin(translated_attribute(value))
66
66
  end
67
67
  end
68
68
  end
@@ -16,7 +16,7 @@ module Decidim
16
16
  end
17
17
 
18
18
  def translated_description
19
- @translated_description ||= decidim_sanitize_editor(translated_attribute(model.settings.description))
19
+ @translated_description ||= decidim_sanitize_editor_admin(translated_attribute(model.settings.description))
20
20
  end
21
21
 
22
22
  def button_url
@@ -6,7 +6,7 @@
6
6
  <% if translated_welcome_text.blank? %>
7
7
  <%= t("decidim.pages.home.hero.welcome", organization: current_organization.name) %>
8
8
  <% else %>
9
- <%= decidim_sanitize translated_welcome_text %>
9
+ <%= decidim_sanitize_admin translated_welcome_text %>
10
10
  <% end %>
11
11
  </h1>
12
12
  </div>
@@ -7,7 +7,7 @@
7
7
  <%= translated_attribute current_organization.highlighted_content_banner_title %>
8
8
  </h1>
9
9
  <span class="text-highlight">
10
- <%= decidim_sanitize_editor translated_attribute current_organization.highlighted_content_banner_short_description %>
10
+ <%= decidim_sanitize_editor_admin translated_attribute current_organization.highlighted_content_banner_short_description %>
11
11
  </span>
12
12
  </div>
13
13
  <div class="columns large-2">
@@ -15,7 +15,7 @@ module Decidim
15
15
  private
16
16
 
17
17
  def organization_description
18
- desc = decidim_sanitize(translated_attribute(current_organization.description))
18
+ desc = decidim_sanitize_admin(translated_attribute(current_organization.description))
19
19
 
20
20
  # Strip the surrounding paragraph tag because it is not allowed within
21
21
  # a <hN> element.
@@ -25,6 +25,14 @@ module Decidim
25
25
  def recipient_user
26
26
  options[:recipient_user]
27
27
  end
28
+
29
+ def custom_url_for_mail_root
30
+ options[:custom_url_for_mail_root]
31
+ end
32
+
33
+ def decidim
34
+ @decidim ||= EngineRouter.new("decidim", {})
35
+ end
28
36
  end
29
37
  end
30
38
  end
@@ -16,7 +16,7 @@
16
16
  <tr>
17
17
  <th>
18
18
  <center>
19
- <%= render partial: "layouts/decidim/mailer_logo.html", locals: { organization: organization } %>
19
+ <%= render partial: "layouts/decidim/mailer_logo.html", locals: { organization: organization, custom_url_for_mail_root: custom_url_for_mail_root } %>
20
20
  </center>
21
21
  </th>
22
22
  </tr>
@@ -27,7 +27,7 @@
27
27
  <tr>
28
28
  <th>
29
29
  <% if organization.official_img_header.attached? %>
30
- <%= link_to organization.official_url do %>
30
+ <%= link_to newsletter.organization_official_url do %>
31
31
  <%= image_tag organization.attached_uploader(:official_img_header).path, alt: "", style: "max-height: 50px", class: "float-right" %>
32
32
  <% end %>
33
33
  <% end %>
@@ -72,8 +72,8 @@
72
72
  <th class="expander"></th>
73
73
  <th class="small-12 first columns cityhall-bar">
74
74
  <div class="decidim-logo" style="float: right; text-align: right; padding-right: 16px">
75
- <% if @custom_url_for_mail_root.present? %>
76
- <%= link_to organization.name.html_safe, @custom_url_for_mail_root %>
75
+ <% if custom_url_for_mail_root.present? %>
76
+ <%= link_to organization.name.html_safe, custom_url_for_mail_root %>
77
77
  <% else %>
78
78
  <%= link_to organization.name.html_safe, decidim.root_url(host: organization.host) %>
79
79
  <% end %>
@@ -24,7 +24,7 @@ table.button table td {
24
24
  <tr>
25
25
  <th>
26
26
  <center>
27
- <%= render partial: "layouts/decidim/mailer_logo.html", locals: { organization: organization } %>
27
+ <%= render partial: "layouts/decidim/mailer_logo.html", locals: { organization: organization, custom_url_for_mail_root: custom_url_for_mail_root } %>
28
28
  </center>
29
29
  </th>
30
30
  </tr>
@@ -35,7 +35,7 @@ table.button table td {
35
35
  <tr>
36
36
  <th>
37
37
  <% if organization.official_img_header.attached? %>
38
- <%= link_to organization.official_url do %>
38
+ <%= link_to newsletter.organization_official_url do %>
39
39
  <%= image_tag organization.attached_uploader(:official_img_header).url(host: organization.host), alt: "", style: "max-height: 50px", class: "float-right" %>
40
40
  <% end %>
41
41
  <% end %>
@@ -111,8 +111,8 @@ table.button table td {
111
111
  <th class="expander"></th>
112
112
  <th class="small-12 first columns cityhall-bar">
113
113
  <div class="decidim-logo" style="float: right; text-align: right; padding-right: 16px">
114
- <% if @custom_url_for_mail_root.present? %>
115
- <%= link_to organization.name.html_safe, @custom_url_for_mail_root %>
114
+ <% if custom_url_for_mail_root.present? %>
115
+ <%= link_to organization.name.html_safe, custom_url_for_mail_root %>
116
116
  <% else %>
117
117
  <%= link_to organization.name.html_safe, decidim.root_url(host: organization.host) %>
118
118
  <% end %>
@@ -31,7 +31,7 @@ module Decidim
31
31
  query = if @current_group.present?
32
32
  @resource.endorsements.where(decidim_user_group_id: @current_group&.id)
33
33
  else
34
- @resource.endorsements.where(author: @current_user)
34
+ @resource.endorsements.where(author: @current_user, decidim_user_group_id: nil)
35
35
  end
36
36
  query.destroy_all
37
37
  end
@@ -7,6 +7,7 @@ module Decidim
7
7
  include UserGroups
8
8
 
9
9
  before_action :enforce_user_groups_enabled
10
+ before_action :ensure_user_group_not_blocked
10
11
 
11
12
  def new
12
13
  enforce_permission_to :create, :user_group, current_user: current_user
@@ -73,6 +74,10 @@ module Decidim
73
74
 
74
75
  private
75
76
 
77
+ def ensure_user_group_not_blocked
78
+ raise ActionController::RoutingError, "Blocked User Group" if user_group&.blocked?
79
+ end
80
+
76
81
  def accepted_user_group
77
82
  @accepted_user_group ||= Decidim::UserGroups::AcceptedUserGroups.for(current_user).find_by(nickname: params[:id])
78
83
  end
@@ -7,9 +7,11 @@ module Decidim
7
7
  skip_before_action :store_current_location
8
8
 
9
9
  helper Decidim::ExternalDomainHelper
10
+ helper_method :external_url
10
11
 
11
12
  before_action :parse_url
12
13
  rescue_from Decidim::InvalidUrlError, with: :invalid_url
14
+ rescue_from URI::InvalidURIError, with: :invalid_url
13
15
 
14
16
  def new
15
17
  headers["X-Robots-Tag"] = "noindex"
@@ -19,24 +21,21 @@ module Decidim
19
21
 
20
22
  def invalid_url
21
23
  flash[:alert] = I18n.t("decidim.links.invalid_url")
22
- redirect_to decidim.root_path
24
+ if request.xhr?
25
+ render "invalid_url"
26
+ else
27
+ redirect_to decidim.root_path
28
+ end
23
29
  end
24
30
 
25
31
  def parse_url
32
+ raise Decidim::InvalidUrlError if params[:external_url].blank?
26
33
  raise Decidim::InvalidUrlError unless external_url
27
-
28
- parts = external_url.match %r{^(([a-z]+):)?//([^/]+)(/.*)?$}
29
- raise Decidim::InvalidUrlError unless parts
30
-
31
- @url_parts = {
32
- protocol: parts[1],
33
- domain: parts[3],
34
- path: parts[4]
35
- }
34
+ raise Decidim::InvalidUrlError unless %w(http https).include?(external_url.scheme)
36
35
  end
37
36
 
38
37
  def external_url
39
- @external_url ||= params[:external_url]
38
+ @external_url ||= URI.parse(params[:external_url])
40
39
  end
41
40
  end
42
41
  end
@@ -13,7 +13,7 @@ module Decidim
13
13
  before_action :ensure_profile_holder
14
14
  before_action :ensure_profile_holder_is_a_group, only: [:members]
15
15
  before_action :ensure_profile_holder_is_a_user, only: [:groups, :following]
16
- before_action :ensure_user_not_blocked, only: [:following, :followers, :badges]
16
+ before_action :ensure_user_not_blocked
17
17
 
18
18
  def show
19
19
  return redirect_to profile_timeline_path(nickname: params[:nickname]) if profile_holder == current_user
@@ -35,6 +35,7 @@ module Decidim
35
35
  end
36
36
 
37
37
  def user_flaggable?
38
+ return if (try(:profile_holder) || try(:profile_user) || try(:model)).try(:blocked)
38
39
  return unless context[:controller].try(:flaggable_controller?)
39
40
 
40
41
  true
@@ -3,10 +3,21 @@
3
3
  module Decidim
4
4
  module ExternalDomainHelper
5
5
  def highlight_domain
6
+ highlighted_domain = [
7
+ external_url.host,
8
+ (external_url.port && [80, 443].include?(external_url.port) ? "" : ":#{external_url.port}")
9
+ ].join
10
+
11
+ path = [
12
+ external_url.path,
13
+ (external_url.query ? "?#{external_url.query}" : ""),
14
+ (external_url.fragment ? "##{external_url.fragment}" : "")
15
+ ].join
16
+
6
17
  tag.div do
7
- content_tag(:span, "#{@url_parts[:protocol]}//") +
8
- content_tag(:span, @url_parts[:domain], class: "alert") +
9
- content_tag(:span, @url_parts[:path])
18
+ content_tag(:span, "#{external_url.scheme}://") +
19
+ content_tag(:span, highlighted_domain, class: "text-alert") +
20
+ content_tag(:span, path)
10
21
  end
11
22
  end
12
23
  end
@@ -24,7 +24,7 @@ module Decidim
24
24
  #
25
25
  # Returns an HTML tag with the icon.
26
26
  def manifest_icon(manifest, options = {})
27
- if manifest.icon
27
+ if manifest.respond_to?(:icon) && manifest.icon.present?
28
28
  external_icon manifest.icon, options
29
29
  else
30
30
  icon "question-mark", options
@@ -42,9 +42,9 @@ module Decidim
42
42
  def resource_icon(resource, options = {})
43
43
  if resource.class.name == "Decidim::Comments::Comment"
44
44
  icon "comment-square", options
45
- elsif resource.respond_to?(:component)
45
+ elsif resource.respond_to?(:component) && resource.component.present?
46
46
  component_icon(resource.component, options)
47
- elsif resource.respond_to?(:manifest)
47
+ elsif resource.respond_to?(:manifest) && resource.manifest.present?
48
48
  manifest_icon(resource.manifest, options)
49
49
  elsif resource.is_a?(Decidim::User)
50
50
  icon "person", options
@@ -31,6 +31,7 @@ module Decidim
31
31
  # this method is used to generate the root link on mail with the utm_codes
32
32
  # If the newsletter_id is nil, it returns the root_url
33
33
  def custom_url_for_mail_root(organization, newsletter_id = nil)
34
+ decidim = EngineRouter.new("decidim", {})
34
35
  if newsletter_id.present?
35
36
  decidim.root_url(host: organization.host) + utm_codes(organization.host, newsletter_id.to_s)
36
37
  else
@@ -16,13 +16,18 @@ module Decidim
16
16
  #
17
17
  # Returns an HTML-safe String.
18
18
  def decidim_sanitize(html, options = {})
19
+ scrubber = options[:scrubber] || Decidim::UserInputScrubber.new
19
20
  if options[:strip_tags]
20
- strip_tags sanitize(html, scrubber: Decidim::UserInputScrubber.new)
21
+ strip_tags sanitize(html, scrubber: scrubber)
21
22
  else
22
- sanitize(html, scrubber: Decidim::UserInputScrubber.new)
23
+ sanitize(html, scrubber: scrubber)
23
24
  end
24
25
  end
25
26
 
27
+ def decidim_sanitize_admin(html, options = {})
28
+ decidim_sanitize(html, { scrubber: Decidim::AdminInputScrubber.new }.merge(options))
29
+ end
30
+
26
31
  def decidim_sanitize_newsletter(html, options = {})
27
32
  if options[:strip_tags]
28
33
  strip_tags sanitize(html, scrubber: Decidim::NewsletterScrubber.new)
@@ -32,7 +37,11 @@ module Decidim
32
37
  end
33
38
 
34
39
  def decidim_sanitize_editor(html, options = {})
35
- content_tag(:div, decidim_sanitize(html, options), class: %w(ql-editor ql-reset-decidim))
40
+ content_tag(:div, decidim_sanitize(html, options), class: %w(ql-editor-display))
41
+ end
42
+
43
+ def decidim_sanitize_editor_admin(html, options = {})
44
+ decidim_sanitize_editor(html, { scrubber: Decidim::AdminInputScrubber.new }.merge(options))
36
45
  end
37
46
 
38
47
  def decidim_html_escape(text)
@@ -102,9 +111,10 @@ module Decidim
102
111
  #
103
112
  # @return ActiveSupport::SafeBuffer
104
113
  def render_sanitized_content(resource, method)
105
- content = present(resource).send(method, links: true, strip_tags: !safe_content?)
114
+ content = present(resource).send(method, links: true, strip_tags: !try(:safe_content?))
106
115
 
107
- return decidim_sanitize(content, {}) unless safe_content?
116
+ return decidim_sanitize(content, {}) unless try(:safe_content?)
117
+ return decidim_sanitize_editor_admin(content, {}) if try(:safe_content_admin?)
108
118
 
109
119
  decidim_sanitize_editor(content)
110
120
  end
@@ -11,14 +11,20 @@ module Decidim
11
11
 
12
12
  helper_method :cell
13
13
 
14
- def newsletter(user, newsletter)
14
+ def newsletter(user, newsletter, preview: false)
15
15
  return if user.email.blank?
16
16
 
17
17
  @organization = user.organization
18
18
  @newsletter = newsletter
19
19
  @user = user
20
-
21
- @custom_url_for_mail_root = custom_url_for_mail_root(@organization, @newsletter.id) if Decidim.config.track_newsletter_links
20
+ @preview = preview
21
+
22
+ @custom_url_for_mail_root =
23
+ if @preview
24
+ "#"
25
+ elsif Decidim.config.track_newsletter_links
26
+ custom_url_for_mail_root(@organization, @newsletter.id)
27
+ end
22
28
  @encrypted_token = Decidim::NewsletterEncryptor.sent_at_encrypted(@user.id, @newsletter.sent_at)
23
29
 
24
30
  with_user(user) do
@@ -40,6 +46,7 @@ module Decidim
40
46
  organization: @organization,
41
47
  newsletter: @newsletter,
42
48
  recipient_user: @user,
49
+ custom_url_for_mail_root: @custom_url_for_mail_root,
43
50
  context: {
44
51
  controller: self
45
52
  }
@@ -56,6 +56,24 @@ module Decidim
56
56
  .find_by(scoped_resource_id: id)
57
57
  end
58
58
 
59
+ def url(**kwargs)
60
+ proxy_url(:newsletter_url, id: id, **kwargs)
61
+ end
62
+
63
+ def notifications_settings_url(**kwargs)
64
+ proxy_url(__method__, **kwargs)
65
+ end
66
+
67
+ def unsubscribe_newsletters_url(**kwargs)
68
+ proxy_url(__method__, **kwargs)
69
+ end
70
+
71
+ def organization_official_url
72
+ return "#" unless sent?
73
+
74
+ organization.official_url || proxy_url(:root_url)
75
+ end
76
+
59
77
  private
60
78
 
61
79
  def author_belongs_to_organization
@@ -63,5 +81,15 @@ module Decidim
63
81
 
64
82
  errors.add(:author, :invalid) unless author.organization == organization
65
83
  end
84
+
85
+ def proxy_url(method, **kwargs)
86
+ return "#" unless sent?
87
+
88
+ router.public_send(method, host: organization.host, **kwargs)
89
+ end
90
+
91
+ def router
92
+ @router ||= EngineRouter.new("decidim", {})
93
+ end
66
94
  end
67
95
  end
@@ -15,5 +15,33 @@ module Decidim
15
15
  has_many :scopes, class_name: "Decidim::Scope", inverse_of: :scope_type, dependent: :nullify
16
16
 
17
17
  validates :name, presence: true
18
+
19
+ before_destroy :detach_dynamic_associations
20
+
21
+ def self.log_presenter_class_for(_log)
22
+ Decidim::AdminLog::ScopeTypePresenter
23
+ end
24
+
25
+ private
26
+
27
+ # This method detaches all records that may have association with the scope
28
+ # type. This cannot be done directly using the `dependent` option in the
29
+ # `has_many` relation in order to avoid tight coupling between the modules.
30
+ #
31
+ # This logic does not have to be applied to any classes that have been
32
+ # defined as `has_many` associations within this model already as they are
33
+ # already handled by the `dependent` option.
34
+ def detach_dynamic_associations
35
+ ActiveRecord::Base.descendants.each do |cls|
36
+ next if cls.abstract_class? || !cls.name&.match?(/^Decidim::/)
37
+ next if [self.class, Decidim::Scope].include?(cls)
38
+
39
+ cls.reflect_on_all_associations(:belongs_to).each do |ref|
40
+ next unless ref.options[:class_name] == self.class.name
41
+
42
+ cls.where(ref.options[:foreign_key] => id).update_all(ref.options[:foreign_key] => nil) # rubocop:disable Rails/SkipsModelValidations
43
+ end
44
+ end
45
+ end
18
46
  end
19
47
  end
@@ -35,8 +35,6 @@ module Decidim
35
35
  has_many :access_grants, class_name: "Doorkeeper::AccessGrant", foreign_key: :resource_owner_id, dependent: :destroy
36
36
  has_many :access_tokens, class_name: "Doorkeeper::AccessToken", foreign_key: :resource_owner_id, dependent: :destroy
37
37
 
38
- has_one :blocking, class_name: "Decidim::UserBlock", foreign_key: :id, primary_key: :block_id, dependent: :destroy
39
-
40
38
  validates :name, presence: true, unless: -> { deleted? }
41
39
  validates :nickname,
42
40
  presence: true,
@@ -17,6 +17,8 @@ module Decidim
17
17
  has_many :notifications, foreign_key: "decidim_user_id", class_name: "Decidim::Notification", dependent: :destroy
18
18
  has_many :following_follows, foreign_key: "decidim_user_id", class_name: "Decidim::Follow", dependent: :destroy
19
19
 
20
+ has_one :blocking, class_name: "Decidim::UserBlock", foreign_key: :id, primary_key: :block_id, dependent: :destroy
21
+
20
22
  # Regex for name & nickname format validations
21
23
  REGEXP_NAME = /\A(?!.*[<>?%&\^*#@()\[\]=+:;"{}\\|])/.freeze
22
24
 
@@ -4,7 +4,7 @@ module Decidim
4
4
  class UserBlock < ApplicationRecord
5
5
  MINIMUM_JUSTIFICATION_LENGTH = 15
6
6
 
7
- belongs_to :user, class_name: "Decidim::User", foreign_key: :decidim_user_id
8
- belongs_to :blocking_user, class_name: "Decidim::User"
7
+ belongs_to :user, class_name: "Decidim::UserBaseEntity", foreign_key: :decidim_user_id
8
+ belongs_to :blocking_user, class_name: "Decidim::UserBaseEntity"
9
9
  end
10
10
  end
@@ -21,7 +21,7 @@ module Decidim
21
21
  foreign_key: :decidim_user_id,
22
22
  source: :user
23
23
 
24
- validates :name, presence: true, uniqueness: { scope: :decidim_organization_id }
24
+ validates :name, presence: true, uniqueness: { scope: :decidim_organization_id }, unless: -> { blocked? }
25
25
 
26
26
  validate :correct_state
27
27
  validate :unique_document_number, if: :has_document_number?
@@ -70,7 +70,9 @@ export default class ClipboardOverride extends Clipboard {
70
70
  const text = ev.clipboardData.getData("text/plain");
71
71
  const files = Array.from(ev.clipboardData.files || []);
72
72
  if (!html && files.length > 0) {
73
- this.quill.uploader.upload(range, files);
73
+ if (typeof this.quill.uploader !== "undefined") {
74
+ this.quill.uploader.upload(range, files);
75
+ }
74
76
  return;
75
77
  }
76
78
  if (html && files.length > 0) {
@@ -79,7 +81,9 @@ export default class ClipboardOverride extends Clipboard {
79
81
  doc.body.childElementCount === 1 &&
80
82
  doc.body.firstElementChild.tagName === "IMG"
81
83
  ) {
82
- this.quill.uploader.upload(range, files);
84
+ if (typeof this.quill.uploader !== "undefined") {
85
+ this.quill.uploader.upload(range, files);
86
+ }
83
87
  return;
84
88
  }
85
89
  }