decidim-core 0.27.0 → 0.27.2
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/amendable/announcement_cell.rb +1 -1
- data/app/cells/decidim/card_m_cell.rb +1 -1
- 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_cell.rb +12 -7
- data/app/commands/decidim/unendorse_resource.rb +1 -1
- data/app/controllers/decidim/devise/invitations_controller.rb +9 -2
- data/app/controllers/decidim/groups_controller.rb +5 -0
- data/app/controllers/decidim/last_activities_controller.rb +5 -2
- data/app/controllers/decidim/links_controller.rb +4 -2
- data/app/controllers/decidim/profiles_controller.rb +1 -1
- data/app/forms/decidim/account_form.rb +2 -2
- data/app/forms/decidim/amendable/form.rb +2 -1
- data/app/forms/decidim/registration_form.rb +2 -2
- data/app/forms/decidim/upload_validation_form.rb +51 -7
- data/app/helpers/decidim/icon_helper.rb +3 -3
- data/app/helpers/decidim/layout_helper.rb +12 -4
- data/app/helpers/decidim/newsletters_helper.rb +1 -0
- data/app/helpers/decidim/sanitize_helper.rb +1 -1
- data/app/mailers/decidim/newsletter_mailer.rb +10 -3
- data/app/mailers/decidim/notification_mailer.rb +1 -0
- data/app/mailers/decidim/notifications_digest_mailer.rb +1 -0
- data/app/models/decidim/newsletter.rb +28 -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/editor/clipboard_override.js +143 -0
- data/app/packs/src/decidim/editor/clipboard_utilities.js +119 -0
- data/app/packs/src/decidim/editor/linebreak_module.js +0 -8
- data/app/packs/src/decidim/editor.js +9 -2
- 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/_editor.scss +129 -0
- data/app/packs/stylesheets/decidim/email.scss +7 -0
- data/app/packs/stylesheets/decidim/extras/_quill.scss +0 -6
- 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/home_stats_presenter.rb +11 -4
- data/app/presenters/decidim/push_notification_presenter.rb +1 -1
- data/app/presenters/decidim/stats_presenter.rb +7 -8
- data/app/presenters/decidim/user_presenter.rb +9 -4
- data/app/queries/decidim/public_activities.rb +1 -0
- data/app/uploaders/decidim/application_uploader.rb +1 -1
- data/app/uploaders/decidim/avatar_uploader.rb +2 -2
- data/app/validators/etiquette_validator.rb +7 -3
- data/app/validators/file_content_type_validator.rb +103 -0
- data/app/validators/passthru_validator.rb +11 -0
- data/app/validators/uploader_content_type_validator.rb +22 -0
- data/app/views/decidim/messaging/conversations/_conversation.html.erb +1 -1
- data/app/views/decidim/newsletter_mailer/newsletter.html.erb +3 -3
- data/app/views/decidim/newsletters/show.html.erb +1 -1
- data/app/views/decidim/notification_mailer/event_received.html.erb +1 -1
- data/app/views/decidim/notifications_digest_mailer/_email_content.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 +5 -17
- data/config/locales/bg.yml +5 -17
- data/config/locales/ca.yml +20 -24
- data/config/locales/cs.yml +12 -17
- data/config/locales/de.yml +2 -18
- data/config/locales/el.yml +4 -18
- data/config/locales/en.yml +11 -15
- data/config/locales/es-MX.yml +13 -17
- data/config/locales/es-PY.yml +13 -17
- data/config/locales/es.yml +22 -26
- data/config/locales/eu.yml +28 -35
- data/config/locales/fi-plain.yml +11 -15
- data/config/locales/fi.yml +12 -16
- data/config/locales/fr-CA.yml +11 -18
- data/config/locales/fr.yml +11 -18
- data/config/locales/ga-IE.yml +0 -2
- data/config/locales/gl.yml +2 -17
- data/config/locales/gn-PY.yml +1 -0
- data/config/locales/hu.yml +4 -18
- data/config/locales/id-ID.yml +5 -17
- data/config/locales/is-IS.yml +0 -1
- data/config/locales/it.yml +1 -18
- data/config/locales/ja.yml +25 -29
- data/config/locales/ka-GE.yml +1 -0
- data/config/locales/lb.yml +0 -17
- data/config/locales/lo-LA.yml +1 -0
- data/config/locales/lt.yml +0 -17
- data/config/locales/lv.yml +5 -17
- data/config/locales/nl.yml +0 -17
- data/config/locales/no.yml +2 -19
- data/config/locales/pl.yml +4 -18
- data/config/locales/pt-BR.yml +0 -17
- data/config/locales/pt.yml +0 -17
- data/config/locales/ro-RO.yml +49 -16
- data/config/locales/ru.yml +5 -3
- data/config/locales/sk.yml +5 -17
- data/config/locales/sv.yml +22 -18
- data/config/locales/tr-TR.yml +4 -18
- data/config/locales/uk.yml +5 -1
- data/config/locales/zh-CN.yml +3 -17
- 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 +93 -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/attributes/localized_date.rb +1 -1
- data/lib/decidim/attributes/time_with_zone.rb +5 -2
- data/lib/decidim/core/engine.rb +7 -5
- data/lib/decidim/core/test/factories.rb +13 -6
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/editor_shared_examples.rb +30 -0
- data/lib/decidim/core/test/shared_examples/mcell_examples.rb +17 -0
- data/lib/decidim/core/test.rb +2 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/dependency_resolver.rb +14 -8
- data/lib/decidim/file_validator_humanizer.rb +1 -1
- data/lib/decidim/form_builder.rb +11 -4
- data/lib/decidim/participatory_space_resourceable.rb +7 -1
- data/lib/decidim/resourceable.rb +5 -4
- data/lib/decidim/settings_manifest.rb +1 -1
- metadata +17 -8
- data/app/packs/images/decidim/gamification/badges/decidim_gamification_badges_invitations.svg +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 391ba34f55c860208f7644dd10b1b3e2b6465ed45b9e9f9fd194ce1036516995
|
|
4
|
+
data.tar.gz: 93636f8d556d73547fcdff45986fcc85ba4a22e9c399fdeca0c550ee6c241363
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 157c005fbea98fe374586f91f15f17bc54450d6e4b6f7136d51582d5cae7af9442d250edbbf4fe2a4308aac902ba0eb28c49681153dcda6b6948f8589414e930
|
|
7
|
+
data.tar.gz: 8ebc9089ad86980956ded3024d490f419bf8015ae0dc4b3fe6e003d415010de8ed28751bd0c168cf526c8a17f5db50467c9223242c2150cf600304990e1eda04
|
|
@@ -36,7 +36,7 @@ module Decidim::Amendable
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def proposal_link(resource = model.amendable, text = nil)
|
|
39
|
-
text ||= %(<strong>#{present(model.amendable).title}</strong>)
|
|
39
|
+
text ||= %(<strong>#{decidim_sanitize(present(model.amendable).title, strip_tags: true)}</strong>)
|
|
40
40
|
link_to resource_locator(resource).path do
|
|
41
41
|
text
|
|
42
42
|
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
|
|
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 %>
|
|
@@ -87,9 +87,18 @@ module Decidim
|
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
def explanation
|
|
90
|
-
|
|
90
|
+
i18n_options = {
|
|
91
|
+
scope: options[:help_i18n_scope].presence || "decidim.forms.upload_help",
|
|
92
|
+
attribute: attribute_translation
|
|
93
|
+
}
|
|
91
94
|
|
|
92
|
-
I18n.t("explanation",
|
|
95
|
+
I18n.t("explanation", **i18n_options)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def attribute_translation
|
|
99
|
+
I18n.t(attribute, scope: [:activemodel, :attributes, resource_class.constantize.model_name.param_key].join("."))
|
|
100
|
+
rescue NameError
|
|
101
|
+
I18n.t(attribute, scope: "activemodel.attributes")
|
|
93
102
|
end
|
|
94
103
|
|
|
95
104
|
def add_attribute
|
|
@@ -145,11 +154,7 @@ module Decidim
|
|
|
145
154
|
end
|
|
146
155
|
|
|
147
156
|
def file_name_for(attachment)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return "(#{filename})" if has_title?
|
|
151
|
-
|
|
152
|
-
filename
|
|
157
|
+
determine_filename(attachment)
|
|
153
158
|
end
|
|
154
159
|
|
|
155
160
|
def determine_filename(attachment)
|
|
@@ -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
|
|
@@ -21,7 +21,7 @@ module Decidim
|
|
|
21
21
|
# invitation. Using the param `invite_redirect` we can redirect the user
|
|
22
22
|
# to a custom path after it has accepted the invitation.
|
|
23
23
|
def after_accept_path_for(resource)
|
|
24
|
-
|
|
24
|
+
invite_redirect_path || after_sign_in_path_for(resource)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# When a managed user accepts the invitation is promoted to non-managed user.
|
|
@@ -32,7 +32,6 @@ module Decidim
|
|
|
32
32
|
resource.update!(newsletter_notifications_at: Time.current) if update_resource_params[:newsletter_notifications]
|
|
33
33
|
resource.update!(managed: false) if resource.managed?
|
|
34
34
|
resource.update!(accepted_tos_version: resource.organization.tos_version)
|
|
35
|
-
Decidim::Gamification.increment_score(resource.invited_by, :invitations) if resource.invited_by
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
resource
|
|
@@ -40,6 +39,14 @@ module Decidim
|
|
|
40
39
|
|
|
41
40
|
protected
|
|
42
41
|
|
|
42
|
+
def invite_redirect_path
|
|
43
|
+
path = params[:invite_redirect]
|
|
44
|
+
return unless path
|
|
45
|
+
return unless path.starts_with?(%r{^/[a-z0-9]+})
|
|
46
|
+
|
|
47
|
+
path
|
|
48
|
+
end
|
|
49
|
+
|
|
43
50
|
def configure_permitted_parameters
|
|
44
51
|
devise_parameter_sanitizer.permit(:accept_invitation, keys: [:nickname, :tos_agreement, :newsletter_notifications])
|
|
45
52
|
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
|
|
@@ -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
|
|
@@ -33,8 +33,11 @@ module Decidim
|
|
|
33
33
|
|
|
34
34
|
def search_collection
|
|
35
35
|
ActionLog
|
|
36
|
-
.where(
|
|
37
|
-
|
|
36
|
+
.where(
|
|
37
|
+
organization: current_organization,
|
|
38
|
+
visibility: %w(public-only all)
|
|
39
|
+
)
|
|
40
|
+
.with_new_resource_type("all")
|
|
38
41
|
.order(created_at: :desc)
|
|
39
42
|
end
|
|
40
43
|
|
|
@@ -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"
|
|
@@ -25,7 +27,7 @@ module Decidim
|
|
|
25
27
|
def parse_url
|
|
26
28
|
raise Decidim::InvalidUrlError unless external_url
|
|
27
29
|
|
|
28
|
-
parts = external_url.match %r{
|
|
30
|
+
parts = external_url.match %r{\A(([a-z]+):)?//([^/]+)(/.*)?\z}
|
|
29
31
|
raise Decidim::InvalidUrlError unless parts
|
|
30
32
|
|
|
31
33
|
@url_parts = {
|
|
@@ -36,7 +38,7 @@ module Decidim
|
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
def external_url
|
|
39
|
-
@external_url ||= params[:external_url]
|
|
41
|
+
@external_url ||= URI.parse(params[:external_url]).to_s
|
|
40
42
|
end
|
|
41
43
|
end
|
|
42
44
|
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
|
|
@@ -19,9 +19,9 @@ module Decidim
|
|
|
19
19
|
attribute :personal_url
|
|
20
20
|
attribute :about
|
|
21
21
|
|
|
22
|
-
validates :name, presence: true
|
|
22
|
+
validates :name, presence: true, format: { with: Decidim::User::REGEXP_NAME }
|
|
23
23
|
validates :email, presence: true, "valid_email_2/email": { disposable: true }
|
|
24
|
-
validates :nickname, presence: true, format: Decidim::User::REGEXP_NICKNAME
|
|
24
|
+
validates :nickname, presence: true, format: { with: Decidim::User::REGEXP_NICKNAME }
|
|
25
25
|
|
|
26
26
|
validates :nickname, length: { maximum: Decidim::User.nickname_max_length, allow_blank: true }
|
|
27
27
|
validates :password, confirmation: true
|
|
@@ -66,7 +66,8 @@ module Decidim
|
|
|
66
66
|
errors = amendable_form_errors.details[key] - @original_form.errors.details[key]
|
|
67
67
|
|
|
68
68
|
errors.map do |hash|
|
|
69
|
-
|
|
69
|
+
error = hash.delete(:error)
|
|
70
|
+
@amendable_form.errors.add(key, error, **hash) unless @amendable_form.errors.details[key].include?(error: error)
|
|
70
71
|
end
|
|
71
72
|
end
|
|
72
73
|
end
|
|
@@ -14,8 +14,8 @@ module Decidim
|
|
|
14
14
|
attribute :tos_agreement, Boolean
|
|
15
15
|
attribute :current_locale, String
|
|
16
16
|
|
|
17
|
-
validates :name, presence: true
|
|
18
|
-
validates :nickname, presence: true, format: Decidim::User::REGEXP_NICKNAME, length: { maximum: Decidim::User.nickname_max_length }
|
|
17
|
+
validates :name, presence: true, format: { with: Decidim::User::REGEXP_NAME }
|
|
18
|
+
validates :nickname, presence: true, format: { with: Decidim::User::REGEXP_NICKNAME }, length: { maximum: Decidim::User.nickname_max_length }
|
|
19
19
|
validates :email, presence: true, "valid_email_2/email": { disposable: true }
|
|
20
20
|
validates :password, confirmation: true
|
|
21
21
|
validates :password, password: { name: :name, email: :email, username: :nickname }
|
|
@@ -7,8 +7,8 @@ module Decidim
|
|
|
7
7
|
include Decidim::HasUploadValidations
|
|
8
8
|
|
|
9
9
|
attribute :resource_class, String
|
|
10
|
-
# Property is named as attribute in upload modal and passthru validator, but
|
|
11
|
-
# cannot be named as attribute here.
|
|
10
|
+
# Property is named as attribute in upload modal and passthru validator, but
|
|
11
|
+
# it cannot be named as attribute here.
|
|
12
12
|
attribute :property, String
|
|
13
13
|
attribute :blob, String
|
|
14
14
|
attribute :form_class, String
|
|
@@ -16,9 +16,22 @@ module Decidim
|
|
|
16
16
|
validates :resource_class, presence: true
|
|
17
17
|
validates :property, presence: true
|
|
18
18
|
validates :blob, presence: true
|
|
19
|
-
validate :
|
|
19
|
+
validate :file_validators, if: ->(form) { form.resource_class.present? && form.property.present? && form.blob.present? }
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
alias organization current_organization
|
|
22
|
+
|
|
23
|
+
# This is a "trick" to provide the attachment context (i.e. admin or
|
|
24
|
+
# participant) to the attachment records being validated. This is to show
|
|
25
|
+
# the invalid content type / file extension errors with the correct file
|
|
26
|
+
# extensions that may be shown in the help text next to the upload
|
|
27
|
+
# drag'n'drop field.
|
|
28
|
+
def attached_to
|
|
29
|
+
@attached_to ||= AttachmentContextProxy.new(organization, attachment_context)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def file_validators
|
|
22
35
|
org = organization
|
|
23
36
|
PassthruValidator.new(
|
|
24
37
|
attributes: [property],
|
|
@@ -31,8 +44,6 @@ module Decidim
|
|
|
31
44
|
).validate_each(self, property.to_sym, blob)
|
|
32
45
|
end
|
|
33
46
|
|
|
34
|
-
private
|
|
35
|
-
|
|
36
47
|
def validate_with
|
|
37
48
|
if form_object_class && form_object_class._validators[property.to_sym].is_a?(Array) && form_object_class._validators[property.to_sym].size.positive?
|
|
38
49
|
passthru = form_object_class._validators[property.to_sym].find { |v| v.is_a?(PassthruValidator) }
|
|
@@ -49,6 +60,39 @@ module Decidim
|
|
|
49
60
|
end
|
|
50
61
|
end
|
|
51
62
|
|
|
52
|
-
|
|
63
|
+
# The attachment context (i.e. admin or participant) is determined using the
|
|
64
|
+
# form class name and checking if it contains the `Admin` namespace in it.
|
|
65
|
+
# And example use case is the attachment forms in the admin panel.
|
|
66
|
+
def attachment_context
|
|
67
|
+
return :participant unless form_object_class
|
|
68
|
+
return :admin if form_object_class.name.include? "::Admin::"
|
|
69
|
+
|
|
70
|
+
:participant
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# This class provides ability to interpret the attachment context based on
|
|
74
|
+
# the details available within the context of this class. Normally the
|
|
75
|
+
# attachment context would be defined by the record to which the attachment
|
|
76
|
+
# are added to, e.g. proposals (participant contenxt) or participatory
|
|
77
|
+
# processes (admin context). Unfortunately this information is not available
|
|
78
|
+
# when the parameters are passed to the upload validation.
|
|
79
|
+
class AttachmentContextProxy
|
|
80
|
+
attr_reader :organization, :attachment_context
|
|
81
|
+
|
|
82
|
+
delegate :id, :_read_attribute, to: :organization
|
|
83
|
+
|
|
84
|
+
def initialize(organization, attachment_context)
|
|
85
|
+
@organization = organization
|
|
86
|
+
@attachment_context = attachment_context
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.primary_key
|
|
90
|
+
:id
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def self.polymorphic_name
|
|
94
|
+
"Decidim::Organization"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
53
97
|
end
|
|
54
98
|
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
|
|
@@ -88,8 +88,11 @@ module Decidim
|
|
|
88
88
|
classes = _icon_classes(options) + ["external-icon"]
|
|
89
89
|
|
|
90
90
|
if path.split(".").last == "svg"
|
|
91
|
+
icon_path = application_path(path)
|
|
92
|
+
return unless icon_path
|
|
93
|
+
|
|
91
94
|
attributes = { class: classes.join(" ") }.merge(options)
|
|
92
|
-
asset = File.read(
|
|
95
|
+
asset = File.read(icon_path)
|
|
93
96
|
asset.gsub("<svg ", "<svg#{tag_builder.tag_options(attributes)} ").html_safe
|
|
94
97
|
else
|
|
95
98
|
image_pack_tag(path, class: classes.join(" "), style: "display: none")
|
|
@@ -97,9 +100,14 @@ module Decidim
|
|
|
97
100
|
end
|
|
98
101
|
|
|
99
102
|
def application_path(path)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
# Force the path to be returned without the protocol and host even when a
|
|
104
|
+
# custom asset host has been defined. The host parameter needs to be a
|
|
105
|
+
# non-nil because otherwise it will be set to the asset host at
|
|
106
|
+
# ActionView::Helpers::AssetUrlHelper#compute_asset_host.
|
|
107
|
+
img_path = asset_pack_path(path, host: "", protocol: :relative)
|
|
108
|
+
Rails.public_path.join(img_path.sub(%r{^/}, ""))
|
|
109
|
+
rescue ::Webpacker::Manifest::MissingEntryError
|
|
110
|
+
nil
|
|
103
111
|
end
|
|
104
112
|
|
|
105
113
|
# Allows to create role attribute according to accessibility rules
|
|
@@ -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
|
|
@@ -37,7 +37,7 @@ module Decidim
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def decidim_sanitize_editor(html, options = {})
|
|
40
|
-
content_tag(:div, decidim_sanitize(html, options), class: %w(ql-editor
|
|
40
|
+
content_tag(:div, decidim_sanitize(html, options), class: %w(ql-editor-display))
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def decidim_sanitize_editor_admin(html, options = {})
|
|
@@ -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
|
}
|
|
@@ -5,6 +5,7 @@ module Decidim
|
|
|
5
5
|
# a events are received.
|
|
6
6
|
class NotificationMailer < Decidim::ApplicationMailer
|
|
7
7
|
helper Decidim::ResourceHelper
|
|
8
|
+
helper Decidim::SanitizeHelper
|
|
8
9
|
|
|
9
10
|
def event_received(event, event_class_name, resource, user, user_role, extra) # rubocop:disable Metrics/ParameterLists
|
|
10
11
|
with_user(user) do
|
|
@@ -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
|
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?
|