decidim-core 0.7.4 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +9 -2
  3. data/app/assets/javascripts/decidim.js.es6 +1 -0
  4. data/app/assets/javascripts/decidim/editor.js.es6 +8 -2
  5. data/app/assets/javascripts/decidim/form_filter.component.js.es6 +2 -2
  6. data/app/assets/javascripts/decidim/foundation.js.es6 +18 -8
  7. data/app/assets/javascripts/decidim/select2.js.es6 +3 -0
  8. data/app/assets/stylesheets/decidim/_decidim.scss +1 -1
  9. data/app/assets/stylesheets/decidim/modules/_buttons.scss +0 -4
  10. data/app/assets/stylesheets/decidim/modules/_cards.scss +41 -1
  11. data/app/assets/stylesheets/decidim/modules/_messages.scss +35 -0
  12. data/app/assets/stylesheets/decidim/modules/_modules.scss +1 -0
  13. data/app/assets/stylesheets/decidim/modules/_navbar.scss +2 -1
  14. data/app/assets/stylesheets/decidim/utils/_settings.scss +363 -69
  15. data/app/commands/decidim/messaging/reply_to_conversation.rb +55 -0
  16. data/app/commands/decidim/messaging/start_conversation.rb +55 -0
  17. data/app/controllers/concerns/decidim/action_authorization.rb +6 -22
  18. data/app/controllers/concerns/decidim/user_profile.rb +5 -3
  19. data/app/controllers/decidim/application_controller.rb +1 -0
  20. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +2 -2
  21. data/app/controllers/decidim/devise/sessions_controller.rb +5 -3
  22. data/app/controllers/decidim/features/base_controller.rb +1 -0
  23. data/app/controllers/decidim/messaging/conversations_controller.rb +81 -0
  24. data/app/controllers/decidim/pages_controller.rb +2 -11
  25. data/app/forms/decidim/messaging/conversation_form.rb +19 -0
  26. data/app/forms/decidim/messaging/message_form.rb +14 -0
  27. data/app/forms/translatable_presence_validator.rb +7 -10
  28. data/app/helpers/decidim/authorization_form_helper.rb +1 -1
  29. data/app/helpers/decidim/cta_button_helper.rb +1 -1
  30. data/app/helpers/decidim/datetime_helper.rb +23 -0
  31. data/app/helpers/decidim/feature_path_helper.rb +4 -2
  32. data/app/helpers/decidim/layout_helper.rb +0 -2
  33. data/app/helpers/decidim/menu_helper.rb +10 -0
  34. data/app/helpers/decidim/messaging/conversation_helper.rb +36 -0
  35. data/app/helpers/decidim/sanitize_helper.rb +19 -0
  36. data/app/helpers/decidim/traceability_helper.rb +89 -0
  37. data/app/helpers/decidim/translations_helper.rb +4 -2
  38. data/app/helpers/decidim/view_hooks_helper.rb +15 -0
  39. data/app/jobs/decidim/email_notification_generator_job.rb +1 -1
  40. data/app/jobs/decidim/notification_generator_for_recipient_job.rb +1 -1
  41. data/app/jobs/decidim/notification_generator_job.rb +1 -1
  42. data/app/mailers/decidim/messaging/conversation_mailer.rb +47 -0
  43. data/app/mailers/decidim/newsletter_mailer.rb +1 -0
  44. data/app/models/decidim/abilities/base_ability.rb +16 -2
  45. data/app/models/decidim/authorization.rb +20 -2
  46. data/app/models/decidim/messaging/conversation.rb +129 -0
  47. data/app/models/decidim/messaging/message.rb +49 -0
  48. data/app/models/decidim/messaging/participation.rb +23 -0
  49. data/app/models/decidim/messaging/receipt.rb +27 -0
  50. data/app/models/decidim/moderation.rb +1 -1
  51. data/app/models/decidim/organization.rb +2 -2
  52. data/app/models/decidim/scope.rb +2 -1
  53. data/app/models/decidim/scope_type.rb +1 -1
  54. data/app/models/decidim/user.rb +11 -5
  55. data/app/models/decidim/user_group.rb +1 -1
  56. data/app/presenters/decidim/inline_menu_presenter.rb +10 -0
  57. data/app/presenters/decidim/menu_presenter.rb +1 -1
  58. data/app/queries/decidim/messaging/user_conversations.rb +29 -0
  59. data/app/scrubbers/decidim/user_input_scrubber.rb +31 -0
  60. data/app/services/decidim/action_authorizer.rb +48 -12
  61. data/app/services/decidim/traceability.rb +91 -0
  62. data/app/views/decidim/messaging/conversation_mailer/new_conversation.html.erb +9 -0
  63. data/app/views/decidim/messaging/conversation_mailer/new_message.html.erb +9 -0
  64. data/app/views/decidim/messaging/conversations/_message.html.erb +20 -0
  65. data/app/views/decidim/messaging/conversations/_reply.html.erb +11 -0
  66. data/app/views/decidim/messaging/conversations/_show.html.erb +21 -0
  67. data/app/views/decidim/messaging/conversations/_start.html.erb +12 -0
  68. data/app/views/decidim/messaging/conversations/create.js.erb +2 -0
  69. data/app/views/decidim/messaging/conversations/index.html.erb +51 -0
  70. data/app/views/decidim/messaging/conversations/new.html.erb +5 -0
  71. data/app/views/decidim/messaging/conversations/show.html.erb +9 -0
  72. data/app/views/decidim/messaging/conversations/update.js.erb +1 -0
  73. data/app/views/decidim/newsletter_mailer/newsletter.html.erb +1 -1
  74. data/app/views/decidim/notifications/_notification.html.erb +1 -1
  75. data/app/views/decidim/shared/_action_authorization_modal.html.erb +11 -1
  76. data/app/views/decidim/shared/_announcement.html.erb +1 -1
  77. data/app/views/decidim/shared/_version_author.html.erb +18 -0
  78. data/app/views/layouts/decidim/_wrapper.html.erb +3 -0
  79. data/app/views/layouts/decidim/user_profile.html.erb +1 -9
  80. data/app/views/pages/decidim_page.html.erb +1 -1
  81. data/app/views/pages/home.html.erb +0 -2
  82. data/app/views/pages/home/_footer_sub_hero.html.erb +5 -3
  83. data/app/views/pages/home/_hero.html.erb +1 -1
  84. data/app/views/pages/home/_highlighted_processes.html.erb +7 -37
  85. data/app/views/pages/home/_sub_hero.html.erb +6 -4
  86. data/config/locales/ca.yml +49 -21
  87. data/config/locales/en.yml +47 -19
  88. data/config/locales/es.yml +48 -20
  89. data/config/locales/eu.yml +51 -23
  90. data/config/locales/fi.yml +50 -22
  91. data/config/locales/fr.yml +50 -22
  92. data/config/locales/it.yml +89 -61
  93. data/config/locales/nl.yml +72 -44
  94. data/config/locales/pl.yml +49 -21
  95. data/config/locales/pt.yml +431 -0
  96. data/config/locales/ru.yml +4 -27
  97. data/config/locales/uk.yml +10 -23
  98. data/config/routes.rb +3 -5
  99. data/db/migrate/20170313095436_add_available_authorizations_to_organization.rb +2 -2
  100. data/db/migrate/20170713131308_migrate_user_roles_to_participatory_process_roles.rb +7 -3
  101. data/db/migrate/20170914092117_add_status_to_authorizations.rb +9 -0
  102. data/db/migrate/20171011194251_add_verification_metadata_to_authorizations.rb +11 -0
  103. data/db/migrate/20171013124505_add_verification_attachment_to_authorizations.rb +9 -0
  104. data/db/migrate/20171023123330_create_decidim_messaging.rb +23 -0
  105. data/db/migrate/20171107103253_create_versions.rb +18 -0
  106. data/db/migrate/20171107103254_add_object_changes_to_versions.rb +14 -0
  107. data/db/migrate/20171117100533_create_decidim_receipts.rb +13 -0
  108. data/db/seeds.rb +13 -3
  109. data/lib/decidim/core.rb +13 -6
  110. data/lib/decidim/core/engine.rb +37 -0
  111. data/lib/decidim/core/test/factories.rb +33 -21
  112. data/lib/decidim/core/test/shared_examples/follows_examples.rb +1 -1
  113. data/lib/decidim/core/test/shared_examples/manage_moderations_examples.rb +6 -11
  114. data/lib/decidim/core/test/shared_examples/process_announcements_examples.rb +2 -4
  115. data/lib/decidim/core/test/shared_examples/reportable.rb +33 -31
  116. data/lib/decidim/core/test/shared_examples/scope_helper_examples.rb +29 -31
  117. data/lib/decidim/core/version.rb +1 -1
  118. data/lib/decidim/engine_router.rb +4 -2
  119. data/lib/decidim/has_reference.rb +10 -2
  120. data/lib/decidim/messaging.rb +9 -0
  121. data/lib/decidim/participable.rb +1 -1
  122. data/lib/decidim/traceable.rb +31 -0
  123. data/lib/decidim/view_hooks.rb +108 -0
  124. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.es.js +4 -2
  125. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.pt.js +14 -0
  126. metadata +179 -113
  127. data/app/commands/decidim/authorize_user.rb +0 -59
  128. data/app/controllers/decidim/authorizations_controller.rb +0 -80
  129. data/app/services/decidim/authorization_handler.rb +0 -95
  130. data/app/views/decidim/authorizations/first_login.html.erb +0 -22
  131. data/app/views/decidim/authorizations/index.html.erb +0 -49
  132. data/app/views/decidim/authorizations/new.html.erb +0 -33
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Decidim
4
- # A command to authorize a user with an authorization handler.
5
- class AuthorizeUser < Rectify::Command
6
- # Public: Initializes the command.
7
- #
8
- # handler - An AuthorizationHandler object.
9
- def initialize(handler)
10
- @handler = handler
11
- end
12
-
13
- # Executes the command. Broadcasts these events:
14
- #
15
- # - :ok when everything is valid.
16
- # - :invalid if the handler wasn't valid and we couldn't proceed.
17
- #
18
- # Returns nothing.
19
- def call
20
- return broadcast(:invalid) unless handler.valid? && unique?
21
-
22
- create_authorization
23
- broadcast(:ok)
24
- end
25
-
26
- private
27
-
28
- attr_reader :handler
29
-
30
- def create_authorization
31
- authorization = Authorization.find_or_initialize_by(
32
- user: handler.user,
33
- name: handler.handler_name
34
- )
35
-
36
- authorization.attributes = {
37
- unique_id: handler.unique_id,
38
- metadata: handler.metadata
39
- }
40
-
41
- authorization.save!
42
- end
43
-
44
- def unique?
45
- return true if handler.unique_id.nil?
46
-
47
- duplicates = Authorization.where(
48
- user: User.where.not(id: handler.user.id).where(organization: handler.user.organization.id),
49
- name: handler.handler_name,
50
- unique_id: handler.unique_id
51
- )
52
-
53
- return true unless duplicates.any?
54
-
55
- handler.errors.add(:base, I18n.t("decidim.authorization_handlers.errors.duplicate_authorization"))
56
- false
57
- end
58
- end
59
- end
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Decidim
4
- # This controller allows users to create and destroy their authorizations. It
5
- # shouldn't be necessary to expand it to add new authorization schemes.
6
- class AuthorizationsController < Decidim::ApplicationController
7
- helper_method :handler, :handlers
8
- before_action :valid_handler, only: [:new, :create]
9
-
10
- include Decidim::UserProfile
11
- helper Decidim::DecidimFormHelper
12
- helper Decidim::CtaButtonHelper
13
- helper Decidim::AuthorizationFormHelper
14
-
15
- layout "layouts/decidim/user_profile", only: [:index]
16
-
17
- def new; end
18
-
19
- def index
20
- @authorizations = current_user.authorizations
21
- end
22
-
23
- def first_login
24
- if handlers.length == 1
25
- redirect_to(
26
- action: :new,
27
- handler: handlers.first.handler_name,
28
- redirect_url: account_path
29
- )
30
- end
31
- end
32
-
33
- def create
34
- AuthorizeUser.call(handler) do
35
- on(:ok) do
36
- flash[:notice] = t("authorizations.create.success", scope: "decidim")
37
- redirect_to params[:redirect_url] || authorizations_path
38
- end
39
-
40
- on(:invalid) do
41
- flash[:alert] = t("authorizations.create.error", scope: "decidim")
42
- render action: :new
43
- end
44
- end
45
- end
46
-
47
- protected
48
-
49
- def handler
50
- @handler ||= AuthorizationHandler.handler_for(handler_name, handler_params)
51
- end
52
-
53
- def handler_params
54
- (params[:authorization_handler] || {}).merge(user: current_user)
55
- end
56
-
57
- def handler_name
58
- params[:handler] || params.dig(:authorization_handler, :handler_name)
59
- end
60
-
61
- def valid_handler
62
- return true if handler
63
-
64
- logger.warn "Invalid authorization handler given: #{handler_name} doesn't"\
65
- "exist or you haven't added it to `Decidim.authorization_handlers`"
66
-
67
- redirect_to(authorizations_path) && (return false)
68
- end
69
-
70
- def handlers
71
- @handlers ||= available_authorization_handlers.reject do |handler|
72
- authorized_handlers.include?(handler.handler_name)
73
- end
74
- end
75
-
76
- def authorized_handlers
77
- current_user.authorizations.map(&:name)
78
- end
79
- end
80
- end
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Decidim
4
- # This is the base class for authorization handlers, all implementations
5
- # should inherit from it.
6
- # Each AuthorizationHandler is a form that will be used to check if the
7
- # authorization is valid or not. When it is valid a new authorization will
8
- # be created for the user.
9
- #
10
- # Feel free to use validations to assert fields against a remote API,
11
- # local database, or whatever.
12
- #
13
- # It also sets two default attributes, `user` and `handler_name`.
14
- class AuthorizationHandler < Form
15
- # The user that is trying to authorize, it's initialized with the
16
- # `current_user` from the controller.
17
- attribute :user, Decidim::User
18
- # The String name of the handler, should not be modified since it's used to
19
- # infer the class name of the authorization handler.
20
- attribute :handler_name, String
21
-
22
- # A unique ID to be implemented by the authorization handler that ensures
23
- # no duplicates are created. This uniqueness check will be skipped if
24
- # unique_id returns nil.
25
- def unique_id
26
- nil
27
- end
28
-
29
- # THe attributes of the handler that should be exposed as form input when
30
- # rendering the handler in a form.
31
- #
32
- # Returns an Array of Strings.
33
- def form_attributes
34
- attributes.except(:id, :user).keys
35
- end
36
-
37
- # The String partial path so Rails can render the handler as a form. This
38
- # is useful if you want to have a custom view to render the form instead of
39
- # the default view.
40
- #
41
- # Example:
42
- #
43
- # A handler named Decidim::CensusHandler would look for its partial in:
44
- # decidim/census/form
45
- #
46
- # Returns a String.
47
- def to_partial_path
48
- handler_name.sub!(/_handler$/, "") + "/form"
49
- end
50
-
51
- # Any data that the developer would like to inject to the `metadata` field
52
- # of an authorization when it's created. Can be useful if some of the
53
- # params the user sent with the authorization form want to be persisted for
54
- # future use.
55
- #
56
- # Returns a Hash.
57
- def metadata
58
- {}
59
- end
60
-
61
- # A serialized version of the handler's name.
62
- #
63
- # Returns a String.
64
- def self.handler_name
65
- name.underscore
66
- end
67
-
68
- # Same as the class method but accessible from the instance.
69
- #
70
- # Returns a String.
71
- def handler_name
72
- self.class.handler_name
73
- end
74
-
75
- # Finds a handler class from a String. This is necessary when processing
76
- # the form data. It will only look for valid handlers that have also been
77
- # configured in `Decidim.authorization_handlers`.
78
- #
79
- # name - The String name of the class to find, usually in the same shape as
80
- # the one returned by `handler_name`.
81
- # params - An optional Hash with params to initialize the handler.
82
- #
83
- # Returns an AuthorizationHandler descendant.
84
- # Returns nil when no handlers could be found.
85
- def self.handler_for(name, params = {})
86
- return unless active_handler?(name)
87
-
88
- name.classify.constantize.from_params(params || {})
89
- end
90
-
91
- def self.active_handler?(name)
92
- name && Decidim.authorization_handlers.include?(name.classify)
93
- end
94
- end
95
- end
@@ -1,22 +0,0 @@
1
- <main class="wrapper">
2
- <div class="row collapse">
3
- <div class="row collapse">
4
- <div class="columns large-8 large-centered text-center">
5
- <h1 class="heading1 page-title"><%= t(".title") %></h1>
6
- <p class="heading5"><%= t(".verify_with_these_options") %></p>
7
- </div>
8
- </div>
9
- <div class="row">
10
- <div class="columns medium-7 large-5 medium-centered">
11
- <div class="card">
12
- <div class="card__content">
13
- <% handlers.each do |handler| %>
14
- <%= link_to t("authorizations.first_login.actions.#{handler.handler_name}", scope: "decidim"), new_authorization_path(handler: handler.handler_name), class: "button expanded" %>
15
- <% end %>
16
- <p class="text-center skip"><%= t("decidim.authorizations.skip_verification", link: link_to(t("decidim.authorizations.start_exploring"), cta_button_path).html_safe).html_safe %>.</p>
17
- </div>
18
- </div>
19
- </div>
20
- </div>
21
- </div>
22
- </main>
@@ -1,49 +0,0 @@
1
- <div class="row column authorizations-list">
2
- <% if @authorizations.any? %>
3
- <section class="section">
4
- <div class="card card--list">
5
- <% @authorizations.each do |authorization| %>
6
- <div class="card--list__item">
7
- <div class="card--list__text">
8
- <%= icon "lock-unlocked", class: "card--list__icon" %>
9
- <div>
10
- <h5 class="card--list__heading">
11
- <%= t("#{authorization.name}.name", scope: "decidim.authorization_handlers") %>
12
- </h5>
13
- <span class="text-small"><%= l(authorization.updated_at, format: :long) %></span>
14
- </div>
15
- </div>
16
- <div class="card--list__data">
17
- <%= link_to new_authorization_path(handler: authorization.name), class: "card--list__data__icon" do %>
18
- <%= icon "reload" %>
19
- <% end %>
20
- </div>
21
- </div>
22
- <% end %>
23
- </div>
24
- <% end %>
25
- <% if handlers.any? %>
26
- <div class="card card--list">
27
- <% handlers.each do |handler| %>
28
- <div class="card--list__item">
29
- <div class="card--list__text">
30
- <a href="#">
31
- <%= icon "lock-locked", class: "card--list__icon" %>
32
- </a>
33
- <div>
34
- <h5 class="card--list__heading">
35
- <%= link_to t("#{handler.handler_name}.name", scope: "decidim.authorization_handlers"), new_authorization_path(handler: handler.handler_name) %>
36
- </h5>
37
- </div>
38
- </div>
39
- <div class="card--list__data">
40
- <%= link_to new_authorization_path(handler: handler.handler_name), class: "card--list__data__icon" do %>
41
- <%= icon "chevron-right" %>
42
- <% end %>
43
- </div>
44
- </div>
45
- <% end %>
46
- </div>
47
- </section>
48
- <% end %>
49
- </div>
@@ -1,33 +0,0 @@
1
- <main class="wrapper">
2
- <div class="row collapse">
3
- <div class="row collapse">
4
- <div class="columns large-8 large-centered text-center page-title">
5
- <h1><%= t(".authorize_with", authorizer: t("#{handler.handler_name}.name", scope: "decidim.authorization_handlers")) %></h1>
6
- </div>
7
- </div>
8
-
9
- <div class="row">
10
- <div class="columns large-6 medium-centered">
11
- <div class="card">
12
- <div class="card__content">
13
- <%= authorization_form_for(handler, url: authorizations_path(redirect_url: params[:redirect_url])) do |form| %>
14
- <%= form.error_for(:base) %>
15
-
16
- <% if lookup_context.exists?(handler.to_partial_path, [], true) %>
17
- <%= render partial: handler.to_partial_path, locals: { handler: handler, form: form } %>
18
- <% else %>
19
- <%= form.all_fields %>
20
- <div class="actions">
21
- <%= form.submit t(".authorize"), class: "button expanded" %>
22
- </div>
23
- <% end %>
24
- <% end %>
25
- <p class="text-center skip">
26
- <%= t("decidim.authorizations.skip_verification", link: link_to(t("decidim.authorizations.start_exploring"), cta_button_path).html_safe).html_safe %>.
27
- </p>
28
- </div>
29
- </div>
30
- </div>
31
- </div>
32
- </div>
33
- </main>