decidim-core 0.27.1 → 0.27.3
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.
- checksums.yaml +4 -4
- data/app/cells/decidim/newsletter_templates/base_cell.rb +8 -0
- data/app/cells/decidim/newsletter_templates/basic_only_text/show.erb +4 -4
- data/app/cells/decidim/newsletter_templates/image_text_cta/show.erb +4 -4
- data/app/cells/decidim/upload_modal/files.erb +1 -0
- data/app/cells/decidim/upload_modal_cell.rb +26 -11
- data/app/commands/decidim/attachment_methods.rb +20 -2
- data/app/commands/decidim/create_registration.rb +1 -0
- data/app/commands/decidim/gallery_methods.rb +1 -1
- data/app/commands/decidim/unendorse_resource.rb +1 -1
- data/app/commands/decidim/update_account.rb +1 -0
- data/app/commands/decidim/update_password.rb +2 -0
- data/app/controllers/decidim/devise/sessions_controller.rb +18 -2
- data/app/controllers/decidim/groups_controller.rb +5 -0
- data/app/controllers/decidim/links_controller.rb +10 -11
- data/app/controllers/decidim/profiles_controller.rb +1 -1
- data/app/helpers/decidim/cells_helper.rb +1 -0
- data/app/helpers/decidim/external_domain_helper.rb +14 -3
- data/app/helpers/decidim/icon_helper.rb +3 -3
- data/app/helpers/decidim/newsletters_helper.rb +1 -0
- data/app/helpers/decidim/sanitize_helper.rb +3 -2
- data/app/mailers/decidim/newsletter_mailer.rb +10 -3
- data/app/models/decidim/newsletter.rb +28 -0
- data/app/models/decidim/scope_type.rb +24 -0
- data/app/models/decidim/user.rb +0 -2
- data/app/models/decidim/user_base_entity.rb +2 -0
- data/app/models/decidim/user_block.rb +2 -2
- data/app/models/decidim/user_group.rb +1 -1
- data/app/packs/src/decidim/direct_uploads/upload_modal.js +0 -1
- data/app/packs/src/decidim/editor/clipboard_override.js +6 -2
- data/app/packs/src/decidim/editor.js +63 -33
- data/app/packs/src/decidim/form_filter.component.test.js +148 -5
- data/app/packs/src/decidim/form_filter.js +26 -4
- data/app/packs/stylesheets/decidim/email.scss +7 -0
- data/app/packs/stylesheets/decidim/modules/_buttons.scss +10 -6
- data/app/packs/stylesheets/decidim/modules/_cards.scss +1 -1
- data/app/packs/stylesheets/decidim/modules/_comments.scss +24 -0
- data/app/packs/stylesheets/decidim/modules/_input-gallery.scss +2 -1
- data/app/packs/stylesheets/decidim/modules/_upload_modal.scss +0 -4
- data/app/packs/stylesheets/decidim/vizzs/_linechart.scss +2 -2
- data/app/packs/stylesheets/decidim/vizzs/_rowchart.scss +2 -2
- data/app/presenters/decidim/admin_log/user_group_presenter.rb +1 -1
- data/app/presenters/decidim/admin_log/user_moderation_presenter.rb +1 -1
- data/app/presenters/decidim/notification_presenter.rb +1 -1
- data/app/presenters/decidim/notification_to_mailer_presenter.rb +1 -0
- data/app/presenters/decidim/push_notification_presenter.rb +1 -1
- data/app/presenters/decidim/user_group_presenter.rb +1 -1
- data/app/presenters/decidim/user_presenter.rb +1 -1
- data/app/scrubbers/decidim/admin_input_scrubber.rb +3 -1
- data/app/scrubbers/decidim/user_input_scrubber.rb +30 -1
- data/app/services/decidim/traceability.rb +1 -0
- data/app/uploaders/decidim/application_uploader.rb +1 -1
- data/app/uploaders/decidim/avatar_uploader.rb +2 -2
- data/app/validators/uploader_image_dimensions_validator.rb +22 -2
- data/app/views/decidim/links/_invalid_url_modal.html.erb +17 -0
- data/app/views/decidim/links/_modal.html.erb +1 -1
- data/app/views/decidim/links/invalid_url.js.erb +24 -0
- data/app/views/decidim/links/new.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/_conversation.html.erb +2 -6
- data/app/views/decidim/newsletter_mailer/newsletter.html.erb +3 -3
- data/app/views/decidim/newsletters/show.html.erb +1 -1
- data/app/views/layouts/decidim/_mailer_logo.html.erb +2 -2
- data/app/views/layouts/decidim/newsletter_base.html.erb +2 -2
- data/config/locales/ar.yml +571 -7
- data/config/locales/bg.yml +6 -8
- data/config/locales/ca.yml +38 -30
- data/config/locales/cs.yml +28 -33
- data/config/locales/da.yml +4 -0
- data/config/locales/de.yml +4 -25
- data/config/locales/el.yml +6 -9
- data/config/locales/en.yml +22 -15
- data/config/locales/eo.yml +2 -1
- data/config/locales/es-MX.yml +30 -22
- data/config/locales/es-PY.yml +30 -22
- data/config/locales/es.yml +36 -28
- data/config/locales/et.yml +4 -0
- data/config/locales/eu.yml +173 -80
- data/config/locales/fa-IR.yml +1 -0
- data/config/locales/fi-plain.yml +7 -20
- data/config/locales/fi.yml +26 -18
- data/config/locales/fr-CA.yml +27 -19
- data/config/locales/fr.yml +25 -17
- data/config/locales/ga-IE.yml +1 -0
- data/config/locales/gl.yml +2 -25
- data/config/locales/gn-PY.yml +4 -0
- data/config/locales/hr.yml +4 -0
- data/config/locales/hu.yml +68 -28
- data/config/locales/id-ID.yml +7 -8
- data/config/locales/is-IS.yml +2 -2
- data/config/locales/it.yml +2 -10
- data/config/locales/ja.yml +30 -37
- data/config/locales/ka-GE.yml +5 -0
- data/config/locales/kaa.yml +1 -0
- data/config/locales/lb.yml +0 -8
- data/config/locales/lt.yml +0 -38
- data/config/locales/lv.yml +5 -7
- data/config/locales/nl.yml +1 -27
- data/config/locales/no.yml +3 -29
- data/config/locales/oc-FR.yml +3 -0
- data/config/locales/pl.yml +4 -39
- data/config/locales/pt-BR.yml +2 -10
- data/config/locales/pt.yml +0 -8
- data/config/locales/ro-RO.yml +85 -7
- data/config/locales/ru.yml +6 -4
- data/config/locales/sk.yml +8 -9
- data/config/locales/sl.yml +1 -0
- data/config/locales/sr-CS.yml +2 -0
- data/config/locales/sv.yml +23 -28
- data/config/locales/tr-TR.yml +7 -12
- data/config/locales/uk.yml +6 -4
- data/config/locales/zh-CN.yml +3 -8
- data/config/locales/zh-TW.yml +1872 -0
- data/lib/decidim/api/types/localized_string_type.rb +9 -0
- data/lib/decidim/api/types/translated_field_type.rb +20 -5
- data/lib/decidim/asset_router/pipeline.rb +95 -0
- data/lib/decidim/asset_router/storage.rb +82 -0
- data/lib/decidim/asset_router.rb +3 -75
- data/lib/decidim/attribute_object/form.rb +9 -0
- data/lib/decidim/core/test/factories.rb +13 -6
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +36 -0
- data/lib/decidim/core/test/shared_examples/digest_mail_examples.rb +33 -0
- data/lib/decidim/core/test/shared_examples/editor_shared_examples.rb +5 -4
- data/lib/decidim/core/test/shared_examples/rich_text_editor_examples.rb +7 -3
- data/lib/decidim/core/test.rb +1 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/dependency_resolver.rb +14 -8
- data/lib/decidim/form_builder.rb +5 -4
- data/lib/decidim/participatory_space_resourceable.rb +7 -1
- data/lib/decidim/publicable.rb +4 -0
- metadata +14 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d6577740d87b562e24f541c4723480ec774239f69a389d4434536ab72be3b116
|
|
4
|
+
data.tar.gz: 8366df277375b9fadc5c96b4a9e647a0300057d7148eafcb672f3a57d3abd55f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f6f4e9e7bcf14ccc5943ec41d4468338d1cf62aec7d37b296d0fa37a3c1c7bc97711b06579d10b32167ce291b8d664989f90eecfcba9a94f228ff60e7e8698e0
|
|
7
|
+
data.tar.gz: 4fcd0dacd12572c3a4b404709ec632dcc6c5cc964dfd9dc29d92a4dd03da2b10ddc3e5df57a6ed91cb3f90e0dac70c4668ba89040f8cf5788e34d1f8e857d3b8
|
|
@@ -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
|
|
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
|
|
76
|
-
<%= link_to organization.name.html_safe,
|
|
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
|
|
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
|
|
115
|
-
<%= link_to organization.name.html_safe,
|
|
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 %>
|
|
@@ -5,6 +5,7 @@ module Decidim
|
|
|
5
5
|
class UploadModalCell < Decidim::ViewModel
|
|
6
6
|
include Cell::ViewModel::Partial
|
|
7
7
|
include ERB::Util
|
|
8
|
+
include Decidim::SanitizeHelper
|
|
8
9
|
|
|
9
10
|
alias form model
|
|
10
11
|
|
|
@@ -29,7 +30,7 @@ module Decidim
|
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
def label
|
|
32
|
-
options[:label]
|
|
33
|
+
form.send(:custom_label, attribute, options[:label], { required: required?, for: nil })
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
def button_label
|
|
@@ -72,8 +73,17 @@ module Decidim
|
|
|
72
73
|
options[:multiple] || false
|
|
73
74
|
end
|
|
74
75
|
|
|
76
|
+
# @deprecated Please use `required?` instead.
|
|
77
|
+
#
|
|
78
|
+
# NOTE: When this is removed, also the `optional` option should be removed.
|
|
75
79
|
def optional
|
|
76
|
-
|
|
80
|
+
!required?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def required?
|
|
84
|
+
return !options[:optional] if options.has_key?(:optional)
|
|
85
|
+
|
|
86
|
+
options[:required] == true
|
|
77
87
|
end
|
|
78
88
|
|
|
79
89
|
# By default Foundation adds form errors next to input, but since input is in the modal
|
|
@@ -81,15 +91,24 @@ module Decidim
|
|
|
81
91
|
# This should only be necessary when file is required by the form.
|
|
82
92
|
def input_validation_field
|
|
83
93
|
object_name = form.object.present? ? "#{form.object.model_name.param_key}[#{add_attribute}_validation]" : "#{add_attribute}_validation"
|
|
84
|
-
input = check_box_tag object_name, 1, attachments.present?, class: "hide", label: false, required:
|
|
94
|
+
input = check_box_tag object_name, 1, attachments.present?, class: "hide", label: false, required: required?
|
|
85
95
|
message = form.send(:abide_error_element, add_attribute) + form.send(:error_and_help_text, add_attribute)
|
|
86
96
|
input + message
|
|
87
97
|
end
|
|
88
98
|
|
|
89
99
|
def explanation
|
|
90
|
-
|
|
100
|
+
i18n_options = {
|
|
101
|
+
scope: options[:help_i18n_scope].presence || "decidim.forms.upload_help",
|
|
102
|
+
attribute: attribute_translation
|
|
103
|
+
}
|
|
91
104
|
|
|
92
|
-
I18n.t("explanation",
|
|
105
|
+
I18n.t("explanation", **i18n_options)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def attribute_translation
|
|
109
|
+
I18n.t(attribute, scope: [:activemodel, :attributes, resource_class.constantize.model_name.param_key].join("."))
|
|
110
|
+
rescue NameError
|
|
111
|
+
I18n.t(attribute, scope: "activemodel.attributes")
|
|
93
112
|
end
|
|
94
113
|
|
|
95
114
|
def add_attribute
|
|
@@ -133,7 +152,7 @@ module Decidim
|
|
|
133
152
|
def title_for(attachment)
|
|
134
153
|
return unless has_title?
|
|
135
154
|
|
|
136
|
-
translated_attribute(attachment.title)
|
|
155
|
+
decidim_html_escape(decidim_sanitize(translated_attribute(attachment.title)))
|
|
137
156
|
end
|
|
138
157
|
|
|
139
158
|
def truncated_file_name_for(attachment, max_length = 31)
|
|
@@ -145,11 +164,7 @@ module Decidim
|
|
|
145
164
|
end
|
|
146
165
|
|
|
147
166
|
def file_name_for(attachment)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return "(#{filename})" if has_title?
|
|
151
|
-
|
|
152
|
-
filename
|
|
167
|
+
determine_filename(attachment)
|
|
153
168
|
end
|
|
154
169
|
|
|
155
170
|
def determine_filename(attachment)
|
|
@@ -12,8 +12,8 @@ module Decidim
|
|
|
12
12
|
@attachment = Attachment.new(
|
|
13
13
|
title: { I18n.locale => @form.attachment.title },
|
|
14
14
|
attached_to: attached_to,
|
|
15
|
-
file: @form.attachment.file,
|
|
16
|
-
content_type: @form.attachment.file
|
|
15
|
+
file: signed_id_for(@form.attachment.file),
|
|
16
|
+
content_type: content_type_for(@form.attachment.file)
|
|
17
17
|
)
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -53,5 +53,23 @@ module Decidim
|
|
|
53
53
|
def delete_attachment?
|
|
54
54
|
@form.attachment&.delete_file.present?
|
|
55
55
|
end
|
|
56
|
+
|
|
57
|
+
protected
|
|
58
|
+
|
|
59
|
+
def signed_id_for(attachment)
|
|
60
|
+
return attachment[:file] if attachment.is_a?(Hash)
|
|
61
|
+
|
|
62
|
+
attachment
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def content_type_for(attachment)
|
|
66
|
+
return attachment.content_type if attachment.instance_of?(ActionDispatch::Http::UploadedFile)
|
|
67
|
+
|
|
68
|
+
blob(signed_id_for(attachment)).content_type
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def blob(signed_id)
|
|
72
|
+
ActiveStorage::Blob.find_signed(signed_id)
|
|
73
|
+
end
|
|
56
74
|
end
|
|
57
75
|
end
|
|
@@ -41,6 +41,7 @@ module Decidim
|
|
|
41
41
|
nickname: form.nickname,
|
|
42
42
|
password: form.password,
|
|
43
43
|
password_confirmation: form.password_confirmation,
|
|
44
|
+
password_updated_at: Time.current,
|
|
44
45
|
organization: form.current_organization,
|
|
45
46
|
tos_agreement: form.tos_agreement,
|
|
46
47
|
newsletter_notifications_at: form.newsletter_at,
|
|
@@ -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
|
|
@@ -6,9 +6,25 @@ module Decidim
|
|
|
6
6
|
class SessionsController < ::Devise::SessionsController
|
|
7
7
|
include Decidim::DeviseControllers
|
|
8
8
|
|
|
9
|
-
# rubocop: disable Rails/LexicallyScopedActionFilter
|
|
10
9
|
before_action :check_sign_in_enabled, only: :create
|
|
11
|
-
|
|
10
|
+
|
|
11
|
+
def create
|
|
12
|
+
super do |user|
|
|
13
|
+
if user.admin?
|
|
14
|
+
# Check that the admin password passes the validation and clear the
|
|
15
|
+
# `password_updated_at` field when the password is weak to force a
|
|
16
|
+
# password update on the user.
|
|
17
|
+
#
|
|
18
|
+
# Handles a case when the user registers through the registration
|
|
19
|
+
# form and they are promoted to an admin after that. In this case,
|
|
20
|
+
# the newly promoted admin user would otherwise have to change their
|
|
21
|
+
# password straight away even if they originally registered with a
|
|
22
|
+
# strong password.
|
|
23
|
+
validator = PasswordValidator.new({ attributes: :password })
|
|
24
|
+
user.update!(password_updated_at: nil) unless validator.validate_each(user, :password, sign_in_params[:password])
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
12
28
|
|
|
13
29
|
def destroy
|
|
14
30
|
current_user.invalidate_all_sessions!
|
|
@@ -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
|
|
@@ -78,6 +79,10 @@ module Decidim
|
|
|
78
79
|
|
|
79
80
|
private
|
|
80
81
|
|
|
82
|
+
def ensure_user_group_not_blocked
|
|
83
|
+
raise ActionController::RoutingError, "Blocked User Group" if user_group&.blocked?
|
|
84
|
+
end
|
|
85
|
+
|
|
81
86
|
def accepted_user_group
|
|
82
87
|
@accepted_user_group ||= Decidim::UserGroups::AcceptedUserGroups.for(current_user).find_by(nickname: params[:id])
|
|
83
88
|
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
|
-
|
|
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
|
|
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
|
|
@@ -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, "#{
|
|
8
|
-
content_tag(:span,
|
|
9
|
-
content_tag(:span,
|
|
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.instance_of?(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
|
|
@@ -112,9 +112,10 @@ module Decidim
|
|
|
112
112
|
#
|
|
113
113
|
# @return ActiveSupport::SafeBuffer
|
|
114
114
|
def render_sanitized_content(resource, method)
|
|
115
|
-
content = present(resource).send(method, links: true, strip_tags: !safe_content?)
|
|
115
|
+
content = present(resource).send(method, links: true, strip_tags: !try(:safe_content?))
|
|
116
116
|
|
|
117
|
-
return decidim_sanitize(content, {}) unless safe_content?
|
|
117
|
+
return decidim_sanitize(content, {}) unless try(:safe_content?)
|
|
118
|
+
return decidim_sanitize_editor_admin(content, {}) if try(:safe_content_admin?)
|
|
118
119
|
|
|
119
120
|
decidim_sanitize_editor(content)
|
|
120
121
|
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
|
-
|
|
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
|
|
@@ -17,8 +17,32 @@ module Decidim
|
|
|
17
17
|
|
|
18
18
|
validates :name, presence: true
|
|
19
19
|
|
|
20
|
+
before_destroy :detach_dynamic_associations
|
|
21
|
+
|
|
20
22
|
def self.log_presenter_class_for(_log)
|
|
21
23
|
Decidim::AdminLog::ScopeTypePresenter
|
|
22
24
|
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
# This method detaches all records that may have association with the scope
|
|
29
|
+
# type. This cannot be done directly using the `dependent` option in the
|
|
30
|
+
# `has_many` relation in order to avoid tight coupling between the modules.
|
|
31
|
+
#
|
|
32
|
+
# This logic does not have to be applied to any classes that have been
|
|
33
|
+
# defined as `has_many` associations within this model already as they are
|
|
34
|
+
# already handled by the `dependent` option.
|
|
35
|
+
def detach_dynamic_associations
|
|
36
|
+
ActiveRecord::Base.descendants.each do |cls|
|
|
37
|
+
next if cls.abstract_class? || !cls.name&.match?(/^Decidim::/)
|
|
38
|
+
next if cls == self.class || cls == Decidim::Scope
|
|
39
|
+
|
|
40
|
+
cls.reflect_on_all_associations(:belongs_to).each do |ref|
|
|
41
|
+
next unless ref.options[:class_name] == self.class.name
|
|
42
|
+
|
|
43
|
+
cls.where(ref.options[:foreign_key] => id).update_all(ref.options[:foreign_key] => nil) # rubocop:disable Rails/SkipsModelValidations
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
23
47
|
end
|
|
24
48
|
end
|
data/app/models/decidim/user.rb
CHANGED
|
@@ -36,8 +36,6 @@ module Decidim
|
|
|
36
36
|
has_many :access_tokens, class_name: "Doorkeeper::AccessToken", foreign_key: :resource_owner_id, dependent: :destroy
|
|
37
37
|
has_many :reminders, foreign_key: "decidim_user_id", class_name: "Decidim::Reminder", dependent: :destroy
|
|
38
38
|
|
|
39
|
-
has_one :blocking, class_name: "Decidim::UserBlock", foreign_key: :id, primary_key: :block_id, dependent: :destroy
|
|
40
|
-
|
|
41
39
|
validates :name, presence: true, unless: -> { deleted? }
|
|
42
40
|
validates :nickname,
|
|
43
41
|
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(?!.*[<>?%&\^*#@()\[\]=+:;"{}\\|])/
|
|
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::
|
|
8
|
-
belongs_to :blocking_user, class_name: "Decidim::
|
|
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?
|
|
@@ -16,7 +16,6 @@ export default class UploadModal {
|
|
|
16
16
|
// - addAttribute - Field name / attribute of resource (e.g. avatar)
|
|
17
17
|
// - resourceName - The resource to which the attribute belongs (e.g. user)
|
|
18
18
|
// - resourceClass - Ruby class of the resource (e.g. Decidim::User)
|
|
19
|
-
// - optional - Defines if file is optional
|
|
20
19
|
// - multiple - Defines if multiple files can be uploaded
|
|
21
20
|
// - titled - Defines if file(s) can have titles
|
|
22
21
|
// - maxFileSize - Defines maximum file size in bytes
|
|
@@ -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
|
|
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
|
|
84
|
+
if (typeof this.quill.uploader !== "undefined") {
|
|
85
|
+
this.quill.uploader.upload(range, files);
|
|
86
|
+
}
|
|
83
87
|
return;
|
|
84
88
|
}
|
|
85
89
|
}
|