decidim-core 0.0.1 → 0.0.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.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/app/assets/config/decidim_core_manifest.js +1 -0
  4. data/app/assets/javascripts/decidim.js.es6 +3 -2
  5. data/app/assets/javascripts/decidim/append_elements.js.es6 +8 -0
  6. data/app/assets/javascripts/decidim/filters.js.es6 +22 -0
  7. data/app/assets/javascripts/decidim/form_filter.component.js.es6 +176 -0
  8. data/app/assets/javascripts/decidim/form_filter.component.test.js +151 -0
  9. data/app/assets/javascripts/decidim/inline_svg.js.es6 +12 -0
  10. data/app/assets/javascripts/decidim/user_registrations.js.es6 +22 -0
  11. data/app/assets/stylesheets/decidim/_variables.scss +1 -1
  12. data/app/assets/stylesheets/decidim/modules/_comments.scss +3 -6
  13. data/app/assets/stylesheets/decidim/modules/_cookie-bar.scss +22 -0
  14. data/app/assets/stylesheets/decidim/modules/_layout.scss +9 -1
  15. data/app/assets/stylesheets/decidim/modules/_navbar.scss +8 -5
  16. data/app/assets/stylesheets/decidim/modules/_order-by.scss +0 -1
  17. data/app/assets/stylesheets/decidim/modules/_process-phase.scss +4 -0
  18. data/app/assets/stylesheets/decidim/modules/_timeline.scss +62 -80
  19. data/app/assets/stylesheets/decidim/modules/_typography.scss +20 -31
  20. data/app/assets/stylesheets/decidim/utils/_fontface.scss +4 -16
  21. data/app/assets/stylesheets/decidim/utils/_settings.scss +29 -26
  22. data/app/assets/stylesheets/decidim/utils/_variables.scss +22 -0
  23. data/app/commands/decidim/authorize_user.rb +17 -1
  24. data/app/commands/decidim/create_omniauth_registration.rb +92 -0
  25. data/app/commands/decidim/create_registration.rb +50 -0
  26. data/app/commands/decidim/invite_user.rb +50 -0
  27. data/app/commands/decidim/invite_user_again.rb +25 -0
  28. data/app/commands/decidim/remove_user_role.rb +26 -0
  29. data/app/controllers/concerns/decidim/feature_settings.rb +27 -0
  30. data/app/controllers/concerns/decidim/filter_resource.rb +71 -0
  31. data/app/controllers/concerns/decidim/form_factory.rb +21 -18
  32. data/app/controllers/concerns/decidim/needs_participatory_process.rb +2 -3
  33. data/app/controllers/decidim/devise/confirmations_controller.rb +2 -0
  34. data/app/controllers/decidim/devise/invitations_controller.rb +4 -0
  35. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +96 -0
  36. data/app/controllers/decidim/devise/passwords_controller.rb +2 -0
  37. data/app/controllers/decidim/devise/registrations_controller.rb +34 -0
  38. data/app/controllers/decidim/devise/sessions_controller.rb +1 -0
  39. data/app/controllers/decidim/pages_controller.rb +10 -2
  40. data/app/controllers/decidim/participatory_process_steps_controller.rb +16 -0
  41. data/app/controllers/decidim/participatory_processes_controller.rb +6 -11
  42. data/app/forms/decidim/form.rb +6 -6
  43. data/app/forms/decidim/invite_admin_form.rb +37 -0
  44. data/app/forms/decidim/omniauth_registration_form.rb +24 -0
  45. data/app/forms/decidim/registration_form.rb +41 -0
  46. data/app/helpers/decidim/filters_helper.rb +21 -0
  47. data/app/helpers/decidim/layout_helper.rb +17 -1
  48. data/app/helpers/decidim/omniauth_helper.rb +23 -0
  49. data/app/helpers/decidim/paginate_helper.rb +21 -0
  50. data/app/helpers/decidim/participatory_process_helper.rb +14 -0
  51. data/app/helpers/decidim/participatory_process_steps_helper.rb +17 -0
  52. data/app/mailers/decidim/decidim_devise_mailer.rb +2 -2
  53. data/app/models/decidim/feature.rb +40 -0
  54. data/app/models/decidim/identity.rb +12 -0
  55. data/app/models/decidim/organization.rb +3 -10
  56. data/app/models/decidim/user.rb +3 -1
  57. data/app/models/decidim/user_group.rb +18 -0
  58. data/app/models/decidim/user_group_membership.rb +9 -0
  59. data/app/services/decidim/authorization_handler.rb +13 -13
  60. data/app/services/decidim/resource_search.rb +52 -0
  61. data/app/uploaders/decidim/organization_logo_uploader.rb +1 -1
  62. data/app/views/decidim/authorizations/new.html.erb +3 -1
  63. data/app/views/decidim/devise/omniauth_registrations/new.html.erb +40 -0
  64. data/app/views/decidim/devise/registrations/new.html.erb +21 -1
  65. data/app/views/decidim/devise/sessions/new.html.erb +1 -0
  66. data/app/views/decidim/devise/shared/_links.html.erb +0 -8
  67. data/app/views/decidim/devise/shared/_omniauth_buttons.html.erb +21 -0
  68. data/app/views/decidim/participatory_process_steps/_participatory_process_step.html.erb +16 -0
  69. data/app/views/decidim/participatory_process_steps/_timeline.html.erb +7 -0
  70. data/app/views/decidim/participatory_process_steps/index.html.erb +12 -0
  71. data/app/views/decidim/participatory_processes/show.html.erb +5 -5
  72. data/app/views/decidim/shared/_login_modal.html.erb +30 -0
  73. data/app/views/devise/mailer/invite_admin.html.erb +17 -0
  74. data/app/views/devise/mailer/invite_admin.text.erb +15 -0
  75. data/app/views/devise/mailer/organization_admin_invitation_instructions.html.erb +1 -1
  76. data/app/views/devise/mailer/organization_admin_invitation_instructions.text.erb +1 -1
  77. data/app/views/layouts/decidim/_application.html.erb +1 -0
  78. data/app/views/layouts/decidim/_header.html.erb +1 -1
  79. data/app/views/layouts/decidim/_meta.html.erb +1 -0
  80. data/app/views/layouts/decidim/_process_header.html.erb +12 -1
  81. data/app/views/layouts/decidim/_process_header_steps.html.erb +1 -0
  82. data/app/views/layouts/decidim/_social_meta.html.erb +11 -0
  83. data/app/views/layouts/decidim/participatory_process.html.erb +4 -0
  84. data/app/views/pages/home.html.erb +29 -2
  85. data/config/i18n-tasks.yml +1 -0
  86. data/config/initializers/devise.rb +10 -1
  87. data/config/locales/ca.yml +45 -3
  88. data/config/locales/en.yml +45 -3
  89. data/config/locales/es.yml +45 -3
  90. data/config/routes.rb +9 -2
  91. data/config/secrets.yml +36 -0
  92. data/db/migrate/20170110133113_add_configuration_to_features.rb +7 -0
  93. data/db/migrate/20170110153807_add_handler_to_organization.rb +5 -0
  94. data/db/migrate/20170116110851_create_identities.rb +11 -0
  95. data/db/migrate/20170116135237_loosen_step_requirements.rb +6 -0
  96. data/db/migrate/20170117142904_add_uniqueness_field_to_authorizations.rb +7 -0
  97. data/db/migrate/20170119145359_create_user_groups.rb +11 -0
  98. data/db/migrate/20170119150255_create_user_group_memberships.rb +12 -0
  99. data/db/migrate/20170119150649_add_show_statistics_to_organization.rb +5 -0
  100. data/db/migrate/20170120120733_add_user_groups_verified.rb +5 -0
  101. data/db/seeds.rb +45 -79
  102. data/lib/decidim/core.rb +8 -0
  103. data/lib/decidim/core/engine.rb +8 -0
  104. data/lib/decidim/core/test/factories.rb +188 -0
  105. data/lib/decidim/core/version.rb +1 -1
  106. data/lib/decidim/devise_failure_app.rb +1 -0
  107. data/lib/decidim/feature_manifest.rb +27 -0
  108. data/lib/decidim/features/base_controller.rb +8 -3
  109. data/lib/decidim/features/settings_manifest.rb +94 -0
  110. data/lib/decidim/filter_form_builder.rb +56 -0
  111. data/lib/decidim/form_builder.rb +4 -7
  112. data/vendor/assets/javascripts/svg-injector.js +464 -0
  113. metadata +142 -26
  114. data/app/assets/stylesheets/decidim/modules/_owl-carousel.scss +0 -72
  115. data/app/assets/stylesheets/decidim/modules/_phase-nav.scss +0 -177
  116. data/app/assets/stylesheets/decidim/utils/_helpers.sass +0 -21
  117. data/app/assets/stylesheets/decidim/utils/_keyframes.sass +0 -13
  118. data/app/assets/stylesheets/decidim/utils/_mixins.sass +0 -33
@@ -0,0 +1,22 @@
1
+ // Decidim Variables
2
+
3
+ $primary: map-get($foundation-palette, primary) !default;
4
+ $secondary: map-get($foundation-palette, secondary) !default;
5
+ $success: map-get($foundation-palette, success) !default;
6
+ $warning: map-get($foundation-palette, warning) !default;
7
+ $alert: map-get($foundation-palette, alert) !default;
8
+
9
+ $light-gray-dark: darken($light-gray, 2.5) !default;
10
+
11
+ $proposals: #238FF7 !default;
12
+ $actions: #57D685 !default;
13
+ $debates: #FA6C96 !default;
14
+ $meetings: #FABC6C !default;
15
+
16
+ $twitter: #55acee !default;
17
+ $facebook: #3b5998 !default;
18
+ $google: #dd4b39 !default;
19
+
20
+ $muted: lighten($body-font-color, 30) !default;
21
+
22
+ $border: 1px solid $medium-gray !default;
@@ -16,7 +16,7 @@ module Decidim
16
16
  #
17
17
  # Returns nothing.
18
18
  def call
19
- return broadcast(:invalid) unless handler.authorized?
19
+ return broadcast(:invalid) unless handler.valid? && unique?
20
20
 
21
21
  create_authorization
22
22
  broadcast(:ok)
@@ -29,9 +29,25 @@ module Decidim
29
29
  def create_authorization
30
30
  Authorization.create!(
31
31
  user: handler.user,
32
+ unique_id: handler.unique_id,
32
33
  name: handler.handler_name,
33
34
  metadata: handler.metadata
34
35
  )
35
36
  end
37
+
38
+ def unique?
39
+ return true if handler.unique_id.nil?
40
+
41
+ duplicates = Authorization.where(
42
+ user: User.where(organization: handler.user.organization.id),
43
+ name: handler.handler_name,
44
+ unique_id: handler.unique_id
45
+ )
46
+
47
+ return true unless duplicates.any?
48
+
49
+ handler.errors.add(:base, I18n.t("decidim.authorization_handlers.errors.duplicate_authorization"))
50
+ false
51
+ end
36
52
  end
37
53
  end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ # A command with all the business logic to create a user from omniauth
4
+ class CreateOmniauthRegistration < Rectify::Command
5
+ # Public: Initializes the command.
6
+ #
7
+ # form - A form object with the params.
8
+ def initialize(form, verified_email = nil)
9
+ @form = form
10
+ @verified_email = verified_email
11
+ end
12
+
13
+ # Executes the command. Broadcasts these events:
14
+ #
15
+ # - :ok when everything is valid.
16
+ # - :invalid if the form wasn't valid and we couldn't proceed.
17
+ #
18
+ # Returns nothing.
19
+ def call
20
+ verify_oauth_signature!
21
+
22
+ begin
23
+ return broadcast(:ok, existing_identity.user) if existing_identity
24
+ return broadcast(:invalid) if form.invalid?
25
+
26
+ transaction do
27
+ create_or_find_user
28
+ create_identity
29
+ end
30
+
31
+ broadcast(:ok, @user)
32
+ rescue ActiveRecord::RecordInvalid
33
+ broadcast(:invalid)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :form, :verified_email
40
+
41
+ def create_or_find_user
42
+ generated_password = SecureRandom.hex
43
+
44
+ @user = User.find_or_initialize_by(
45
+ email: verified_email,
46
+ organization: organization
47
+ )
48
+
49
+ unless @user.persisted?
50
+ @user.email = (verified_email || form.email)
51
+ @user.name = form.name
52
+ @user.password = generated_password
53
+ @user.password_confirmation = generated_password
54
+ @user.skip_confirmation! if verified_email
55
+ end
56
+
57
+ @user.tos_agreement = "1"
58
+ @user.save!
59
+ end
60
+
61
+ def create_identity
62
+ @user.identities.create!(
63
+ provider: form.provider,
64
+ uid: form.uid
65
+ )
66
+ end
67
+
68
+ def organization
69
+ @form.current_organization
70
+ end
71
+
72
+ def existing_identity
73
+ @existing_identity ||= Identity.where(
74
+ user: organization.users,
75
+ provider: form.provider,
76
+ uid: form.uid
77
+ ).first
78
+ end
79
+
80
+ def verify_oauth_signature!
81
+ raise InvalidOauthSignature, "Invalid oauth signature: #{form.oauth_signature}" unless signature_valid?
82
+ end
83
+
84
+ def signature_valid?
85
+ signature = OmniauthRegistrationForm.create_signature(form.provider, form.uid)
86
+ form.oauth_signature == signature
87
+ end
88
+ end
89
+
90
+ class InvalidOauthSignature < StandardError
91
+ end
92
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ # A command with all the business logic to create a user through the sign up form.
4
+ # It enables the option to sign up as a user group.
5
+ class CreateRegistration < Rectify::Command
6
+ # Public: Initializes the command.
7
+ #
8
+ # form - A form object with the params.
9
+ def initialize(form)
10
+ @form = form
11
+ end
12
+
13
+ # Executes the command. Broadcasts these events:
14
+ #
15
+ # - :ok when everything is valid.
16
+ # - :invalid if the form wasn't valid and we couldn't proceed.
17
+ #
18
+ # Returns nothing.
19
+ def call
20
+ return broadcast(:invalid) if form.invalid?
21
+
22
+ transaction do
23
+ create_user
24
+ create_user_group if form.is_user_group?
25
+ end
26
+
27
+ broadcast(:ok, @user)
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :form
33
+
34
+ def create_user
35
+ @user = User.create!(email: form.email,
36
+ name: form.name,
37
+ password: form.password,
38
+ password_confirmation: form.password_confirmation,
39
+ organization: form.current_organization,
40
+ tos_agreement: form.tos_agreement)
41
+ end
42
+
43
+ def create_user_group
44
+ UserGroupMembership.create!(user: @user,
45
+ user_group: UserGroup.new(name: form.user_group_name,
46
+ document_number: form.user_group_document_number,
47
+ phone: form.user_group_phone))
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ # A command with the business logic to invite a user to an organization.
4
+ class InviteUser < Rectify::Command
5
+ # Public: Initializes the command.
6
+ #
7
+ # form - A form object with the params.
8
+ def initialize(form)
9
+ @form = form
10
+ end
11
+
12
+ def call
13
+ return broadcast(:invalid) if form.invalid?
14
+
15
+ if user.present?
16
+ set_user_roles
17
+ else
18
+ invite_user
19
+ end
20
+
21
+ broadcast(:ok)
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :form
27
+
28
+ def user
29
+ @user ||= Decidim::User.where(organization: form.organization).where(email: form.email.downcase).first
30
+ end
31
+
32
+ def set_user_roles
33
+ user.roles += form.roles
34
+ user.save!
35
+ end
36
+
37
+ def invite_user
38
+ Decidim::User.invite!(
39
+ {
40
+ name: form.name,
41
+ email: form.email.downcase,
42
+ organization: form.organization,
43
+ roles: form.roles
44
+ },
45
+ form.invited_by,
46
+ invitation_instructions: form.invitation_instructions
47
+ )
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ # A command with the business logic to invite an user to an organization.
4
+ class InviteUserAgain < Rectify::Command
5
+ # Public: Initializes the command.
6
+ #
7
+ # form - A form object with the params.
8
+ def initialize(user, instructions)
9
+ @user = user
10
+ @instructions = instructions
11
+ end
12
+
13
+ def call
14
+ return broadcast(:invalid) unless user&.invited_to_sign_up?
15
+
16
+ user.deliver_invitation(invitation_instructions: instructions)
17
+
18
+ broadcast(:ok)
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :user, :instructions
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ # A command to remove a role from a given User.
4
+ class RemoveUserRole < Rectify::Command
5
+ # Public: Initializes the command.
6
+ #
7
+ # form - A form object with the params.
8
+ def initialize(user, role)
9
+ @user = user
10
+ @role = role
11
+ end
12
+
13
+ def call
14
+ return broadcast(:invalid) unless user
15
+
16
+ user.roles.delete(role.to_s)
17
+ user.save!
18
+
19
+ broadcast(:ok)
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :user, :role
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ require "active_support/concern"
3
+
4
+ module Decidim
5
+ # This concern groups methods and helpers related to accessing the settings
6
+ # of a feature from a controller.
7
+ module FeatureSettings
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ include NeedsParticipatoryProcess
12
+
13
+ helper_method :feature_settings, :current_settings
14
+
15
+ def feature_settings
16
+ current_feature.settings
17
+ end
18
+
19
+ def current_settings
20
+ active_step = current_participatory_process.active_step
21
+ return nil unless active_step
22
+
23
+ current_feature.step_settings.fetch(active_step.id.to_s)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:disable Metrics/BlockLength
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ # Common logic to filter resources
7
+ module FilterResource
8
+ extend ActiveSupport::Concern
9
+
10
+ # Internal: Defines a class that will wrap in an object the URL params used by the filter.
11
+ # this way we can use Rails' form helpers and have automatically checked checkboxes and
12
+ # radio buttons in the view, for example.
13
+ class Filter
14
+ def initialize(filter)
15
+ @filter = filter
16
+ end
17
+
18
+ def method_missing(method_name, *_arguments)
19
+ @filter.present? && @filter.key?(method_name) ? @filter[method_name] : super
20
+ end
21
+
22
+ def respond_to_missing?(method_name, include_private = false)
23
+ @filter.present? && @filter.key?(method_name) || super
24
+ end
25
+ end
26
+
27
+ included do
28
+ helper_method :search, :filter
29
+
30
+ private
31
+
32
+ def search
33
+ @search ||= search_klass.new(search_params)
34
+ end
35
+
36
+ def search_klass
37
+ raise NotImplementedError, "A search class is neeeded to filter resources"
38
+ end
39
+
40
+ def filter
41
+ @filter ||= Filter.new(filter_params)
42
+ end
43
+
44
+ def search_params
45
+ default_search_params
46
+ .merge(filter_params)
47
+ .merge(context_params)
48
+ end
49
+
50
+ def filter_params
51
+ default_filter_params
52
+ .merge(params.to_unsafe_h[:filter].try(:symbolize_keys) || {})
53
+ end
54
+
55
+ def default_search_params
56
+ {}
57
+ end
58
+
59
+ def default_filter_params
60
+ {}
61
+ end
62
+
63
+ def context_params
64
+ {
65
+ feature: current_feature,
66
+ current_user: current_user
67
+ }
68
+ end
69
+ end
70
+ end
71
+ end
@@ -33,45 +33,48 @@ module Decidim
33
33
  # Initializes the form factory object.
34
34
  #
35
35
  # klass - the class name of the Form object that will be initialized
36
- # context - the Controller where the form is built.
37
- def initialize(klass, context)
36
+ # controller - the Controller where the form is built.
37
+ def initialize(klass, controller)
38
38
  @klass = klass
39
- @context = context
39
+ @controller = controller
40
40
  end
41
41
 
42
42
  # Returns a simple instance of the form klass.
43
- def instance(context = {})
44
- @klass.new(context)
43
+ #
44
+ # extra_context - A Hash with optional extra context data.
45
+ def instance(extra_context = {})
46
+ @klass.new(context.merge(extra_context))
45
47
  end
46
48
 
47
49
  # Initializes a form object from a model. Delegates the functionality
48
50
  # to the form object class method.
49
51
  #
50
- # model - the model instance from which the form object will be
51
- # initialized.
52
- # context - a Hash with optional context data.
53
- def from_model(model, context = {})
54
- from_params(model.attributes, context)
52
+ # model - the model instance from which the form object will be
53
+ # initialized.
54
+ # extra_context - a Hash with optional context data.
55
+ def from_model(model, extra_context = {})
56
+ @klass.from_model(model).with_context(context.merge(extra_context))
55
57
  end
56
58
 
57
59
  # Initializes a form object instance from params, and it
58
60
  # automatically adds some context. Context can be extended.
59
61
  #
60
- # params - a Hash with params. Mostly a set of params from a form.
61
- # context - a Hash with optional context data.
62
- def from_params(params, context = {})
63
- @klass.from_params(params, context_hash.merge(context))
62
+ # params - a Hash with params. Mostly a set of params from a form.
63
+ # extra_context - a Hash with optional context data.
64
+ def from_params(params, extra_context = {})
65
+ @klass.from_params(params).with_context(context.merge(extra_context))
64
66
  end
65
67
 
66
68
  # Sets a base context from the current controller. Since this can be
67
69
  # used from some controllers that do not respond to the helper
68
70
  # methods used here, this Hash can have different keys depending on
69
71
  # the controller that uses it.
70
- def context_hash
72
+ def context
71
73
  {
72
- current_organization: @context.try(:current_organization),
73
- current_user: @context.try(:current_user)
74
- }.compact
74
+ current_organization: @controller.try(:current_organization),
75
+ current_feature: @controller.try(:current_feature),
76
+ current_user: @controller.try(:current_user)
77
+ }
75
78
  end
76
79
  end.new(klass, self)
77
80
  end