decidim-core 0.8.4 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +1 -1
- data/app/assets/images/decidim/decidim-logo.svg +23 -23
- data/app/assets/images/decidim/default-avatar.svg +7 -7
- data/app/assets/images/decidim/icons.svg +1 -0
- data/app/assets/javascripts/decidim.js.es6 +5 -2
- data/app/assets/javascripts/decidim/append_redirect_url_to_modals.js.es6 +84 -0
- data/app/assets/javascripts/decidim/data_picker.js.es6 +177 -0
- data/app/assets/javascripts/decidim/form_filter.component.js.es6 +25 -20
- data/app/assets/javascripts/decidim/form_filter.component.test.js +24 -13
- data/app/assets/javascripts/decidim/history.js.es6 +3 -3
- data/app/assets/stylesheets/decidim/_decidim.scss +1 -4
- data/app/assets/stylesheets/decidim/_variables.scss +4 -4
- data/app/assets/stylesheets/decidim/editor.scss +13 -0
- data/app/assets/stylesheets/decidim/email.css +9 -1
- data/app/assets/stylesheets/decidim/extras/_add_comments.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_announcement.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_collection-sort-controls.scss +2 -2
- data/app/assets/stylesheets/decidim/extras/_embed.scss +6 -5
- data/app/assets/stylesheets/decidim/extras/_impersonation-bar.scss +4 -0
- data/app/assets/stylesheets/decidim/extras/_label-required.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_leaflet.scss +6 -4
- data/app/assets/stylesheets/decidim/extras/_meeting-registrations.scss +4 -4
- data/app/assets/stylesheets/decidim/extras/_process_stats.scss +11 -4
- data/app/assets/stylesheets/decidim/extras/_proposal_form.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_quill.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_reference.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_register_form.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_results-per-page.scss +10 -10
- data/app/assets/stylesheets/decidim/extras/_social_icons_mini.scss +4 -3
- data/app/assets/stylesheets/decidim/layouts/_highlighted_banner.scss +38 -0
- data/app/assets/stylesheets/decidim/layouts/_home.scss +33 -3
- data/app/assets/stylesheets/decidim/layouts/_user.scss +33 -5
- data/app/assets/stylesheets/decidim/layouts/_view.scss +1 -2
- data/app/assets/stylesheets/decidim/map.css +5 -3
- data/app/assets/stylesheets/decidim/modules/_address.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_author-avatar.scss +24 -9
- data/app/assets/stylesheets/decidim/modules/_buttons.scss +24 -10
- data/app/assets/stylesheets/decidim/modules/_callout.scss +5 -1
- data/app/assets/stylesheets/decidim/modules/_card-grid.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_cards.scss +102 -31
- data/app/assets/stylesheets/decidim/modules/_comments.scss +21 -20
- data/app/assets/stylesheets/decidim/modules/_cookie-bar.scss +4 -0
- data/app/assets/stylesheets/decidim/modules/_data-picker.scss +159 -0
- data/app/assets/stylesheets/decidim/modules/_datepicker.scss +36 -36
- data/app/assets/stylesheets/decidim/modules/_definition-data.scss +12 -9
- data/app/assets/stylesheets/decidim/modules/_extra.scss +4 -1
- data/app/assets/stylesheets/decidim/modules/_filter-tags.scss +3 -0
- data/app/assets/stylesheets/decidim/modules/_filters.scss +9 -5
- data/app/assets/stylesheets/decidim/modules/_flag.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_footer.scss +10 -0
- data/app/assets/stylesheets/decidim/modules/_forms.scss +2 -1
- data/app/assets/stylesheets/decidim/modules/_help.scss +2 -0
- data/app/assets/stylesheets/decidim/modules/_icons.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_layout.scss +4 -0
- data/app/assets/stylesheets/decidim/modules/_list-docs.scss +3 -0
- data/app/assets/stylesheets/decidim/modules/_main-container.scss +13 -7
- data/app/assets/stylesheets/decidim/modules/_map.scss +13 -1
- data/app/assets/stylesheets/decidim/modules/_margins.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_messages.scss +2 -1
- data/app/assets/stylesheets/decidim/modules/_modules.scss +3 -0
- data/app/assets/stylesheets/decidim/modules/_navbar.scss +36 -16
- data/app/assets/stylesheets/decidim/modules/_omnipresent_banner.scss +26 -0
- data/app/assets/stylesheets/decidim/modules/_opinion-toggle.scss +5 -0
- data/app/assets/stylesheets/decidim/modules/_order-by.scss +10 -10
- data/app/assets/stylesheets/decidim/modules/_pagination.scss +3 -2
- data/app/assets/stylesheets/decidim/modules/_process-header.scss +11 -2
- data/app/assets/stylesheets/decidim/modules/_process-info.scss +9 -1
- data/app/assets/stylesheets/decidim/modules/_process-nav.scss +20 -3
- data/app/assets/stylesheets/decidim/modules/_process-phase.scss +12 -3
- data/app/assets/stylesheets/decidim/modules/_progress-bar.scss +69 -0
- data/app/assets/stylesheets/decidim/modules/_reference.scss +1 -2
- data/app/assets/stylesheets/decidim/modules/_reveal.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_share.scss +2 -0
- data/app/assets/stylesheets/decidim/modules/_signup.scss +5 -1
- data/app/assets/stylesheets/decidim/modules/_static-pages.scss +6 -0
- data/app/assets/stylesheets/decidim/modules/_status-labels.scss +2 -0
- data/app/assets/stylesheets/decidim/modules/_tags.scss +3 -1
- data/app/assets/stylesheets/decidim/modules/_timeline.scss +41 -30
- data/app/assets/stylesheets/decidim/modules/_title-action.scss +2 -1
- data/app/assets/stylesheets/decidim/modules/_typography.scss +13 -4
- data/app/assets/stylesheets/decidim/modules/_user-form.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_video.scss +2 -2
- data/app/assets/stylesheets/decidim/utils/_fontface.scss +22 -20
- data/app/assets/stylesheets/decidim/utils/_helpers.scss +6 -6
- data/app/assets/stylesheets/decidim/utils/_keyframes.scss +6 -6
- data/app/assets/stylesheets/decidim/utils/_mixins.scss +24 -7
- data/app/assets/stylesheets/decidim/utils/_settings.scss +50 -52
- data/app/assets/stylesheets/decidim/utils/_toggle-expand.scss +1 -0
- data/app/commands/decidim/create_omniauth_registration.rb +3 -0
- data/app/commands/decidim/create_registration.rb +3 -1
- data/app/commands/decidim/destroy_account.rb +1 -0
- data/app/commands/decidim/invite_user_again.rb +1 -1
- data/app/commands/decidim/messaging/reply_to_conversation.rb +1 -3
- data/app/commands/decidim/unsubscribe_settings.rb +29 -0
- data/app/commands/decidim/update_account.rb +16 -3
- data/app/controllers/concerns/decidim/action_authorization.rb +1 -1
- data/app/controllers/concerns/decidim/devise_controllers.rb +10 -0
- data/app/controllers/concerns/decidim/form_factory.rb +2 -1
- data/app/controllers/concerns/decidim/impersonate_users.rb +13 -8
- data/app/controllers/concerns/decidim/participatory_space_context.rb +1 -1
- data/app/controllers/decidim/application_controller.rb +16 -0
- data/app/controllers/decidim/cookie_policy_controller.rb +2 -0
- data/app/controllers/decidim/devise/invitations_controller.rb +9 -1
- data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +10 -1
- data/app/controllers/decidim/devise/sessions_controller.rb +9 -1
- data/app/controllers/decidim/locales_controller.rb +2 -3
- data/app/controllers/decidim/messaging/conversations_controller.rb +2 -2
- data/app/controllers/decidim/newsletters_controller.rb +60 -0
- data/app/controllers/decidim/pages_controller.rb +1 -0
- data/app/controllers/decidim/profiles_controller.rb +23 -0
- data/app/controllers/decidim/scopes_controller.rb +19 -20
- data/app/events/decidim/profile_updated_event.rb +27 -0
- data/app/forms/decidim/account_form.rb +34 -0
- data/app/forms/decidim/form.rb +1 -0
- data/app/forms/decidim/messaging/conversation_form.rb +5 -2
- data/app/forms/decidim/omniauth_registration_form.rb +5 -0
- data/app/forms/decidim/registration_form.rb +8 -1
- data/app/helpers/decidim/action_authorization_helper.rb +2 -2
- data/app/helpers/decidim/application_helper.rb +8 -0
- data/app/helpers/decidim/feature_path_helper.rb +12 -2
- data/app/helpers/decidim/feature_reference_helper.rb +1 -1
- data/app/helpers/decidim/messaging/conversation_helper.rb +27 -9
- data/app/helpers/decidim/newsletters_helper.rb +49 -0
- data/app/helpers/decidim/scopes_helper.rb +43 -2
- data/app/helpers/decidim/translations_helper.rb +6 -2
- data/app/mailers/decidim/decidim_devise_mailer.rb +1 -3
- data/app/mailers/decidim/messaging/conversation_mailer.rb +1 -1
- data/app/mailers/decidim/newsletter_mailer.rb +7 -8
- data/app/models/decidim/abilities/everyone_ability.rb +1 -0
- data/app/models/decidim/authorization.rb +19 -5
- data/app/models/decidim/impersonation_log.rb +2 -1
- data/app/models/decidim/messaging/conversation.rb +2 -0
- data/app/models/decidim/messaging/message.rb +4 -0
- data/app/models/decidim/organization.rb +1 -0
- data/app/models/decidim/scope.rb +10 -2
- data/app/models/decidim/user.rb +10 -2
- data/app/presenters/decidim/home_stats_presenter.rb +10 -4
- data/app/presenters/decidim/user_group_presenter.rb +28 -0
- data/app/presenters/decidim/user_presenter.rb +42 -0
- data/app/services/decidim/action_authorizer.rb +32 -68
- data/app/services/decidim/notification_generator_for_recipient.rb +8 -3
- data/app/uploaders/decidim/avatar_uploader.rb +2 -2
- data/app/views/decidim/account/delete.html.erb +1 -1
- data/app/views/decidim/account/show.html.erb +4 -1
- data/app/views/decidim/devise/invitations/edit.html.erb +2 -0
- data/app/views/decidim/devise/omniauth_registrations/new.html.erb +7 -1
- data/app/views/decidim/devise/registrations/new.html.erb +7 -1
- data/app/views/decidim/messaging/conversations/_message.html.erb +6 -12
- data/app/views/decidim/messaging/conversations/_reply.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/index.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/update.js.erb +1 -0
- data/app/views/decidim/newsletter_mailer/newsletter.html.erb +11 -0
- data/app/views/decidim/newsletters/show.html.erb +11 -0
- data/app/views/decidim/newsletters/unsubscribe.html.erb +4 -0
- data/app/views/decidim/notifications/_notification.html.erb +1 -1
- data/app/views/decidim/profiles/show.html.erb +64 -0
- data/app/views/decidim/scopes/_scopes_picker_input.html.erb +6 -0
- data/app/views/decidim/scopes/picker.html.erb +36 -0
- data/app/views/decidim/shared/_action_authorization_modal.html.erb +25 -51
- data/app/views/decidim/shared/_author.html.erb +21 -0
- data/app/views/decidim/shared/_author_reference.html.erb +12 -0
- data/app/views/layouts/decidim/_application.html.erb +1 -0
- data/app/views/layouts/decidim/_impersonation_warning.html.erb +1 -1
- data/app/views/layouts/decidim/_mailer_logo.html.erb +6 -1
- data/app/views/layouts/decidim/_omnipresent_banner.html.erb +14 -0
- data/app/views/layouts/decidim/_user_menu.html.erb +3 -0
- data/app/views/layouts/decidim/mailer.html.erb +16 -4
- data/app/views/layouts/decidim/widget.html.erb +14 -9
- data/app/views/pages/home.html.erb +2 -0
- data/app/views/pages/home/_highlighted_content_banner.html.erb +26 -0
- data/config/initializers/devise.rb +1 -3
- data/config/locales/ca.yml +67 -9
- data/config/locales/en.yml +65 -4
- data/config/locales/es.yml +74 -14
- data/config/locales/eu.yml +66 -4
- data/config/locales/fi.yml +87 -25
- data/config/locales/fr.yml +71 -9
- data/config/locales/gl.yml +493 -0
- data/config/locales/it.yml +79 -17
- data/config/locales/nl.yml +71 -9
- data/config/locales/pl.yml +66 -4
- data/config/locales/pt-BR.yml +493 -0
- data/config/locales/pt.yml +99 -37
- data/config/locales/ru.yml +85 -13
- data/config/locales/sv.yml +493 -0
- data/config/locales/uk.yml +78 -16
- data/config/routes.rb +11 -1
- data/db/migrate/20171212103803_create_unique_nicknames.rb +29 -0
- data/db/migrate/20180115090038_extend_user_profile.rb +8 -0
- data/db/migrate/20180123125308_add_enable_omnipresent_banner_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180123125409_add_omnipresent_banner_title_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180123125432_add_omnipresent_banner_short_description_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180123125452_add_omnipresent_banner_url_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180125063433_add_highlighted_content_banner_to_decidim_organizations.rb +13 -0
- data/db/seeds.rb +8 -2
- data/lib/decidim/abilities/participatory_process_role_ability.rb +1 -3
- data/lib/decidim/content_parsers.rb +8 -0
- data/lib/decidim/content_parsers/base_parser.rb +58 -0
- data/lib/decidim/content_parsers/user_parser.rb +46 -0
- data/lib/decidim/content_processor.rb +84 -0
- data/lib/decidim/content_renderers.rb +8 -0
- data/lib/decidim/content_renderers/base_renderer.rb +37 -0
- data/lib/decidim/content_renderers/user_renderer.rb +32 -0
- data/lib/decidim/core.rb +66 -1
- data/lib/decidim/core/api/author_interface.rb +3 -3
- data/lib/decidim/core/api/user_group_type.rb +10 -8
- data/lib/decidim/core/api/user_type.rb +13 -7
- data/lib/decidim/core/engine.rb +7 -5
- data/lib/decidim/core/test.rb +1 -1
- data/lib/decidim/core/test/factories.rb +21 -45
- data/lib/decidim/core/test/shared_examples/announcements_examples.rb +3 -2
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +5 -2
- data/lib/decidim/core/test/shared_examples/scope_helper_examples.rb +40 -3
- data/lib/decidim/core/test/shared_examples/simple_event.rb +73 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/events.rb +2 -0
- data/lib/decidim/events/author_event.rb +41 -0
- data/lib/decidim/events/base_event.rb +28 -3
- data/lib/decidim/events/email_event.rb +1 -1
- data/lib/decidim/events/notification_event.rb +1 -1
- data/lib/decidim/events/simple_event.rb +79 -0
- data/lib/decidim/filter_form_builder.rb +2 -3
- data/lib/decidim/form_builder.rb +39 -27
- data/lib/decidim/friendly_dates.rb +26 -0
- data/lib/decidim/has_feature.rb +1 -0
- data/lib/decidim/has_reference.rb +1 -1
- data/lib/decidim/i18n_exceptions.rb +1 -3
- data/lib/decidim/menu.rb +1 -1
- data/lib/decidim/newsletter_encryptor.rb +22 -0
- data/lib/decidim/nicknamizable.rb +56 -0
- data/lib/decidim/participable.rb +8 -0
- data/lib/decidim/participatory_space_manifest.rb +10 -1
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.gl.js +13 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.pt-br.js +14 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.pt.js +5 -1
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.ru.js +4 -1
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.sv.js +14 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.uk.js +4 -1
- data/vendor/assets/javascripts/form_datepicker.js.es6 +4 -2
- data/vendor/assets/javascripts/foundation-datepicker.js +42 -26
- metadata +124 -84
- data/app/assets/javascripts/decidim/select2.field.js.es6 +0 -47
- data/app/assets/javascripts/decidim/select2.js.es6 +0 -11
- data/app/assets/stylesheets/decidim/editor.sass +0 -4
- data/app/assets/stylesheets/decidim/plugins/_select2.scss +0 -63
- data/app/helpers/decidim/datetime_helper.rb +0 -23
- data/app/queries/decidim/freetext_scopes.rb +0 -39
- data/lib/decidim/core/test/shared_examples/manage_moderations_examples.rb +0 -64
@@ -11,8 +11,12 @@ module Decidim
|
|
11
11
|
#
|
12
12
|
# Returns a String with the translation.
|
13
13
|
def translated_attribute(attribute)
|
14
|
-
attribute.
|
15
|
-
|
14
|
+
return "" if attribute.nil?
|
15
|
+
return attribute unless attribute.is_a?(Hash)
|
16
|
+
|
17
|
+
attribute[I18n.locale.to_s].presence ||
|
18
|
+
attribute[current_organization.default_locale].presence ||
|
19
|
+
attribute[attribute.keys.first].presence ||
|
16
20
|
""
|
17
21
|
end
|
18
22
|
|
@@ -19,9 +19,7 @@ module Decidim
|
|
19
19
|
@organization = user.organization
|
20
20
|
@opts = opts
|
21
21
|
|
22
|
-
if opts[:invitation_instructions]
|
23
|
-
opts[:subject] = I18n.t("devise.mailer.#{opts[:invitation_instructions]}.subject", organization: user.organization.name)
|
24
|
-
end
|
22
|
+
opts[:subject] = I18n.t("devise.mailer.#{opts[:invitation_instructions]}.subject", organization: user.organization.name) if opts[:invitation_instructions]
|
25
23
|
end
|
26
24
|
|
27
25
|
devise_mail(user, opts[:invitation_instructions] || :invitation_instructions, opts)
|
@@ -3,24 +3,23 @@
|
|
3
3
|
module Decidim
|
4
4
|
class NewsletterMailer < ApplicationMailer
|
5
5
|
helper Decidim::SanitizeHelper
|
6
|
+
include Decidim::NewslettersHelper
|
7
|
+
|
6
8
|
add_template_helper Decidim::TranslationsHelper
|
7
9
|
|
8
10
|
def newsletter(user, newsletter)
|
9
11
|
@organization = user.organization
|
10
12
|
@newsletter = newsletter
|
13
|
+
@user = user
|
11
14
|
|
15
|
+
@custom_url_for_mail_root = custom_url_for_mail_root(@organization, @newsletter.id) if Decidim.config.track_newsletter_links
|
16
|
+
@encrypted_token = Decidim::NewsletterEncryptor.sent_at_encrypted(@user.id, @newsletter.sent_at)
|
12
17
|
with_user(user) do
|
13
|
-
@subject = parse_interpolations(@newsletter.subject[I18n.locale.to_s], user)
|
14
|
-
@body = parse_interpolations(@newsletter.body[I18n.locale.to_s], user)
|
18
|
+
@subject = parse_interpolations(@newsletter.subject[I18n.locale.to_s], user, @newsletter.id)
|
19
|
+
@body = parse_interpolations(@newsletter.body[I18n.locale.to_s], user, @newsletter.id)
|
15
20
|
|
16
21
|
mail(to: "#{user.name} <#{user.email}>", subject: @subject)
|
17
22
|
end
|
18
23
|
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def parse_interpolations(content, user)
|
23
|
-
content.gsub("%{name}", user.name)
|
24
|
-
end
|
25
24
|
end
|
26
25
|
end
|
@@ -31,14 +31,28 @@ module Decidim
|
|
31
31
|
!granted_at.nil?
|
32
32
|
end
|
33
33
|
|
34
|
+
# Calculates at when this authorization will expire, if it needs to.
|
35
|
+
#
|
36
|
+
# Returns nil if the authorization does not expire.
|
37
|
+
# Returns an ActiveSupport::TimeWithZone if it expires.
|
38
|
+
def expires_at
|
39
|
+
return unless workflow_manifest
|
40
|
+
return if workflow_manifest.expires_in.zero?
|
41
|
+
(granted_at || created_at) + workflow_manifest.expires_in
|
42
|
+
end
|
43
|
+
|
44
|
+
def expired?
|
45
|
+
expires_at.present? && expires_at < Time.zone.now
|
46
|
+
end
|
47
|
+
|
34
48
|
private
|
35
49
|
|
36
50
|
def active_handler?
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
51
|
+
workflow_manifest.present?
|
52
|
+
end
|
53
|
+
|
54
|
+
def workflow_manifest
|
55
|
+
@workflow_manifest ||= Decidim::Verifications.find_workflow_manifest(name)
|
42
56
|
end
|
43
57
|
end
|
44
58
|
end
|
@@ -10,7 +10,8 @@ module Decidim
|
|
10
10
|
|
11
11
|
validate :same_organization, :non_active_impersonation
|
12
12
|
|
13
|
-
scope :active, -> { where(ended_at: nil) }
|
13
|
+
scope :active, -> { where(ended_at: nil, expired_at: nil) }
|
14
|
+
scope :expired, -> { where(ended_at: nil).where.not(expired_at: nil) }
|
14
15
|
|
15
16
|
def ended?
|
16
17
|
ended_at.present?
|
@@ -8,6 +8,8 @@ module Decidim
|
|
8
8
|
# message, namely, the interlocutors of the sender in the conversation.
|
9
9
|
#
|
10
10
|
class Message < ApplicationRecord
|
11
|
+
include Decidim::FriendlyDates
|
12
|
+
|
11
13
|
belongs_to :sender,
|
12
14
|
foreign_key: :decidim_sender_id,
|
13
15
|
class_name: "Decidim::User"
|
@@ -24,6 +26,8 @@ module Decidim
|
|
24
26
|
validates :sender, :body, presence: true
|
25
27
|
validates :body, length: { maximum: 1_000 }
|
26
28
|
|
29
|
+
default_scope { order(created_at: :asc) }
|
30
|
+
|
27
31
|
validate :sender_is_participant
|
28
32
|
|
29
33
|
#
|
@@ -23,6 +23,7 @@ module Decidim
|
|
23
23
|
mount_uploader :official_img_footer, Decidim::OfficialImageFooterUploader
|
24
24
|
mount_uploader :logo, Decidim::OrganizationLogoUploader
|
25
25
|
mount_uploader :favicon, Decidim::OrganizationFaviconUploader
|
26
|
+
mount_uploader :highlighted_content_banner_image, ImageUploader
|
26
27
|
|
27
28
|
# Returns top level scopes for this organization.
|
28
29
|
#
|
data/app/models/decidim/scope.rb
CHANGED
@@ -47,11 +47,19 @@ module Decidim
|
|
47
47
|
organization.scopes.where("? = ANY(decidim_scopes.part_of)", id)
|
48
48
|
end
|
49
49
|
|
50
|
+
def ancestor_of?(scope)
|
51
|
+
scope && scope.part_of.member?(id)
|
52
|
+
end
|
53
|
+
|
50
54
|
# Gets the scopes from the part_of list in descending order (first the top level scope, last itself)
|
51
55
|
#
|
56
|
+
# root - The root scope to start retrieval. If present, ignores top level scopes until reaching the root scope.
|
57
|
+
#
|
52
58
|
# Returns an array of Scope objects
|
53
|
-
def part_of_scopes
|
54
|
-
|
59
|
+
def part_of_scopes(root = nil)
|
60
|
+
scope_ids = part_of
|
61
|
+
scope_ids.select! { |id| id == root.id || !root.part_of.member?(id) } if root
|
62
|
+
organization.scopes.where(id: scope_ids).sort { |s1, s2| part_of.index(s2.id) <=> part_of.index(s1.id) }
|
55
63
|
end
|
56
64
|
|
57
65
|
private
|
data/app/models/decidim/user.rb
CHANGED
@@ -6,6 +6,9 @@ require "valid_email2"
|
|
6
6
|
module Decidim
|
7
7
|
# A User is a citizen that wants to join the platform to participate.
|
8
8
|
class User < ApplicationRecord
|
9
|
+
include Nicknamizable
|
10
|
+
include Decidim::Followable
|
11
|
+
|
9
12
|
OMNIAUTH_PROVIDERS = [:facebook, :twitter, :google_oauth2, (:developer if Rails.env.development?)].compact
|
10
13
|
ROLES = %w(admin user_manager).freeze
|
11
14
|
|
@@ -18,14 +21,14 @@ module Decidim
|
|
18
21
|
has_many :identities, foreign_key: "decidim_user_id", class_name: "Decidim::Identity", dependent: :destroy
|
19
22
|
has_many :memberships, class_name: "Decidim::UserGroupMembership", foreign_key: :decidim_user_id, dependent: :destroy
|
20
23
|
has_many :user_groups, through: :memberships, class_name: "Decidim::UserGroup", foreign_key: :decidim_user_group_id
|
21
|
-
has_many :follows, foreign_key: "decidim_user_id", class_name: "Decidim::Follow", dependent: :destroy
|
22
24
|
has_many :notifications, foreign_key: "decidim_user_id", class_name: "Decidim::Notification", dependent: :destroy
|
23
25
|
|
24
26
|
validates :name, presence: true, unless: -> { deleted? }
|
27
|
+
validates :nickname, presence: true, unless: -> { deleted? || managed? }
|
25
28
|
validates :locale, inclusion: { in: :available_locales }, allow_blank: true
|
26
29
|
validates :tos_agreement, acceptance: true, allow_nil: false, on: :create
|
27
30
|
validates :avatar, file_size: { less_than_or_equal_to: ->(_record) { Decidim.maximum_avatar_size } }
|
28
|
-
validates :email, uniqueness: { scope: :organization }, unless: -> { deleted? || managed? }
|
31
|
+
validates :email, :nickname, uniqueness: { scope: :organization }, unless: -> { deleted? || managed? }
|
29
32
|
validates :email, 'valid_email_2/email': { disposable: true }
|
30
33
|
|
31
34
|
validate :all_roles_are_valid
|
@@ -66,6 +69,11 @@ module Decidim
|
|
66
69
|
deleted_at.present?
|
67
70
|
end
|
68
71
|
|
72
|
+
# Public: whether the user has been officialized or not
|
73
|
+
def officialized?
|
74
|
+
!officialized_at.nil?
|
75
|
+
end
|
76
|
+
|
69
77
|
def follows?(followable)
|
70
78
|
Decidim::Follow.where(user: self, followable: followable).any?
|
71
79
|
end
|
@@ -51,13 +51,13 @@ module Decidim
|
|
51
51
|
def global_stats(conditions)
|
52
52
|
Decidim.stats.except([:users_count, :processes_count])
|
53
53
|
.filter(conditions)
|
54
|
-
.with_context(
|
54
|
+
.with_context(organization)
|
55
55
|
.map { |name, data| [name, data] }
|
56
56
|
end
|
57
57
|
|
58
58
|
def feature_stats(conditions)
|
59
|
-
Decidim.feature_manifests.
|
60
|
-
feature.stats.filter(conditions).with_context(published_features).map { |name, data| [name, data] }
|
59
|
+
Decidim.feature_manifests.flat_map do |feature|
|
60
|
+
feature.stats.filter(conditions).with_context(published_features).map { |name, data| [name, data] }
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -74,8 +74,14 @@ module Decidim
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
def public_participatory_spaces
|
78
|
+
@public_participatory_spaces ||= Decidim.participatory_space_manifests.flat_map do |manifest|
|
79
|
+
manifest.participatory_spaces.call(organization).public_spaces
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
77
83
|
def published_features
|
78
|
-
@published_features ||= Feature.where(participatory_space:
|
84
|
+
@published_features ||= Feature.where(participatory_space: public_participatory_spaces).published
|
79
85
|
end
|
80
86
|
end
|
81
87
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
#
|
5
|
+
# Decorator for user groups
|
6
|
+
#
|
7
|
+
class UserGroupPresenter < SimpleDelegator
|
8
|
+
def nickname
|
9
|
+
""
|
10
|
+
end
|
11
|
+
|
12
|
+
def deleted?
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def badge
|
17
|
+
return "" unless verified?
|
18
|
+
|
19
|
+
"verified-badge"
|
20
|
+
end
|
21
|
+
|
22
|
+
def profile_path
|
23
|
+
""
|
24
|
+
end
|
25
|
+
|
26
|
+
delegate :url, to: :avatar, prefix: true
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
#
|
5
|
+
# Decorator for users
|
6
|
+
#
|
7
|
+
class UserPresenter < SimpleDelegator
|
8
|
+
include Rails.application.routes.mounted_helpers
|
9
|
+
include ActionView::Helpers::UrlHelper
|
10
|
+
|
11
|
+
#
|
12
|
+
# nickname presented in a twitter-like style
|
13
|
+
#
|
14
|
+
def nickname
|
15
|
+
"@#{super}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def badge
|
19
|
+
return "" unless officialized?
|
20
|
+
|
21
|
+
"verified-badge"
|
22
|
+
end
|
23
|
+
|
24
|
+
delegate :url, to: :avatar, prefix: true
|
25
|
+
|
26
|
+
def profile_url
|
27
|
+
return "" if deleted?
|
28
|
+
|
29
|
+
decidim.profile_url(__getobj__.nickname, host: __getobj__.organization.host)
|
30
|
+
end
|
31
|
+
|
32
|
+
def profile_path
|
33
|
+
return "" if deleted?
|
34
|
+
|
35
|
+
decidim.profile_path(__getobj__.nickname)
|
36
|
+
end
|
37
|
+
|
38
|
+
def display_mention
|
39
|
+
link_to nickname, profile_path, class: "user-mention"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -4,94 +4,64 @@ module Decidim
|
|
4
4
|
# This class is used to authorize a user against an action in the context of a
|
5
5
|
# feature.
|
6
6
|
class ActionAuthorizer
|
7
|
-
|
8
|
-
|
7
|
+
#
|
9
8
|
# Initializes the ActionAuthorizer.
|
10
9
|
#
|
11
10
|
# user - The user to authorize against.
|
12
11
|
# feature - The feature to authenticate against.
|
13
12
|
# action - The action to authenticate.
|
13
|
+
#
|
14
14
|
def initialize(user, feature, action)
|
15
15
|
@user = user
|
16
16
|
@feature = feature
|
17
17
|
@action = action.to_s if action
|
18
18
|
end
|
19
19
|
|
20
|
-
# Public: Broadcasts different events given the status of the authentication.
|
21
20
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
21
|
+
# Authorize user to perform an action in the context of a feature.
|
22
|
+
#
|
23
|
+
# Returns:
|
24
|
+
# :ok an empty hash - When there is no authorization handler related to the action.
|
25
|
+
# result of authorization handler check - When there is an authorization handler related to the action. Check Decidim::Verifications::DefaultActionAuthorizer class docs.
|
27
26
|
#
|
28
|
-
# Returns nil.
|
29
27
|
def authorize
|
30
|
-
status_code, fields = *status_data
|
31
|
-
|
32
|
-
status(status_code, fields || {})
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def status_data
|
38
28
|
raise AuthorizationError, "Missing data" unless feature && action
|
39
29
|
|
40
|
-
if
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
:pending
|
46
|
-
elsif unmatched_fields.any?
|
47
|
-
[:invalid, fields: unmatched_fields]
|
48
|
-
elsif missing_fields.any?
|
49
|
-
[:incomplete, fields: missing_fields]
|
50
|
-
else
|
51
|
-
:ok
|
52
|
-
end
|
53
|
-
end
|
30
|
+
status_code, data = if authorization_handler_name
|
31
|
+
authorization_handler.authorize(authorization, permission_options)
|
32
|
+
else
|
33
|
+
[:ok, {}]
|
34
|
+
end
|
54
35
|
|
55
|
-
|
56
|
-
AuthorizationStatus.new(status_code, authorization_handler_name, data)
|
36
|
+
AuthorizationStatus.new(status_code, authorization_handler, data)
|
57
37
|
end
|
58
38
|
|
39
|
+
private
|
40
|
+
|
59
41
|
attr_reader :user, :feature, :action
|
60
42
|
|
61
43
|
def authorization
|
62
|
-
return nil unless user
|
44
|
+
return nil unless user && authorization_handler_name
|
63
45
|
|
64
|
-
|
65
|
-
return nil unless handler
|
66
|
-
|
67
|
-
@authorization ||= Verifications::Authorizations.new(user: user, name: handler).first
|
46
|
+
@authorization ||= Verifications::Authorizations.new(user: user, name: authorization_handler_name).first
|
68
47
|
end
|
69
48
|
|
70
|
-
def
|
71
|
-
|
72
|
-
unmatched[field] = permission_options[field] if authorization.metadata[field] != permission_options[field]
|
73
|
-
unmatched
|
74
|
-
end
|
75
|
-
end
|
49
|
+
def authorization_handler
|
50
|
+
return unless authorization_handler_name
|
76
51
|
|
77
|
-
|
78
|
-
permission_options.keys.each_with_object([]) do |field, missing|
|
79
|
-
missing << field if authorization.metadata[field].blank?
|
80
|
-
missing
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def permission_options
|
85
|
-
permission["options"] || {}
|
52
|
+
@authorization_handler ||= Verifications::Adapter.from_element(authorization_handler_name)
|
86
53
|
end
|
87
54
|
|
88
55
|
def authorization_handler_name
|
89
56
|
permission&.fetch("authorization_handler_name", nil)
|
90
57
|
end
|
91
58
|
|
59
|
+
def permission_options
|
60
|
+
permission&.fetch("options", {})
|
61
|
+
end
|
62
|
+
|
92
63
|
def permission
|
93
|
-
return nil unless feature
|
94
|
-
return nil unless action
|
64
|
+
return nil unless feature && action
|
95
65
|
|
96
66
|
@permission ||= feature.permissions&.fetch(action, nil)
|
97
67
|
end
|
@@ -99,32 +69,26 @@ module Decidim
|
|
99
69
|
class AuthorizationStatus
|
100
70
|
attr_reader :code, :data
|
101
71
|
|
102
|
-
def initialize(code,
|
72
|
+
def initialize(code, authorization_handler, data)
|
103
73
|
@code = code.to_sym
|
104
|
-
@
|
74
|
+
@authorization_handler = authorization_handler
|
105
75
|
@data = data.symbolize_keys
|
106
76
|
end
|
107
77
|
|
108
|
-
def auth_method
|
109
|
-
return unless @handler_name
|
110
|
-
|
111
|
-
@auth_method ||= Verifications::Adapter.from_element(@handler_name)
|
112
|
-
end
|
113
|
-
|
114
78
|
def current_path(redirect_url: nil)
|
115
|
-
return unless
|
79
|
+
return unless @authorization_handler
|
116
80
|
|
117
81
|
if pending?
|
118
|
-
|
82
|
+
@authorization_handler.resume_authorization_path(redirect_url: redirect_url)
|
119
83
|
else
|
120
|
-
|
84
|
+
@authorization_handler.root_path(redirect_url: redirect_url)
|
121
85
|
end
|
122
86
|
end
|
123
87
|
|
124
88
|
def handler_name
|
125
|
-
return unless
|
89
|
+
return unless @authorization_handler
|
126
90
|
|
127
|
-
|
91
|
+
@authorization_handler.key
|
128
92
|
end
|
129
93
|
|
130
94
|
def ok?
|