decidim-core 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/decidim/modules/_card-grid.scss +2 -2
  3. data/app/assets/stylesheets/decidim/modules/_filters.scss +3 -3
  4. data/app/assets/stylesheets/decidim/modules/_main-container.scss +1 -5
  5. data/app/assets/stylesheets/decidim/modules/_process-nav.scss +1 -2
  6. data/app/constraints/decidim/current_participatory_process.rb +1 -1
  7. data/app/controllers/concerns/decidim/needs_authorization.rb +2 -3
  8. data/app/controllers/concerns/decidim/needs_participatory_process.rb +1 -1
  9. data/app/controllers/concerns/decidim/{feature_settings.rb → settings.rb} +1 -1
  10. data/app/controllers/decidim/features/base_controller.rb +1 -2
  11. data/app/controllers/decidim/pages_controller.rb +1 -1
  12. data/app/helpers/decidim/feature_path_helper.rb +1 -1
  13. data/{lib → app/models}/decidim/abilities/admin_ability.rb +1 -0
  14. data/app/models/decidim/abilities/base_ability.rb +34 -0
  15. data/{lib → app/models}/decidim/abilities/participatory_process_admin_ability.rb +4 -0
  16. data/{lib → app/models}/decidim/abilities/participatory_process_collaborator_ability.rb +4 -0
  17. data/{lib → app/models}/decidim/abilities/participatory_process_moderator_ability.rb +0 -0
  18. data/app/models/decidim/feature.rb +3 -78
  19. data/app/models/decidim/organization.rb +0 -2
  20. data/app/models/decidim/participatory_process.rb +2 -16
  21. data/app/models/decidim/participatory_process_group.rb +1 -2
  22. data/app/models/decidim/participatory_process_user_role.rb +9 -0
  23. data/app/models/decidim/user.rb +0 -7
  24. data/app/presenters/decidim/home_stats_presenter.rb +1 -1
  25. data/app/presenters/decidim/resource_locator_presenter.rb +57 -15
  26. data/app/queries/decidim/highlighted_participatory_processes.rb +1 -2
  27. data/app/queries/decidim/organization_participatory_process_groups.rb +14 -0
  28. data/app/queries/decidim/organization_participatory_processes.rb +2 -6
  29. data/app/queries/decidim/organization_prioritized_participatory_processes.rb +3 -3
  30. data/app/queries/decidim/organization_published_participatory_processes.rb +17 -0
  31. data/app/queries/decidim/participatory_processes_with_user_role.rb +1 -1
  32. data/app/queries/decidim/prioritized_participatory_processes.rb +1 -1
  33. data/app/queries/decidim/published_participatory_processes.rb +10 -0
  34. data/app/views/layouts/decidim/_process_header.html.erb +2 -2
  35. data/config/locales/ca.yml +19 -0
  36. data/config/locales/es.yml +19 -0
  37. data/config/locales/fr.yml +2 -2
  38. data/db/migrate/20170608142521_add_organization_to_user_groups.rb +16 -3
  39. data/db/seeds.rb +17 -12
  40. data/lib/decidim/abilities.rb +0 -4
  41. data/lib/decidim/abilities/participatory_process_role_ability.rb +4 -1
  42. data/lib/decidim/core.rb +20 -20
  43. data/lib/decidim/core/api/decidim_type.rb +1 -1
  44. data/lib/decidim/core/api/process_step_type.rb +2 -2
  45. data/lib/decidim/core/api/process_type.rb +1 -1
  46. data/lib/decidim/core/api/session_type.rb +1 -1
  47. data/lib/decidim/core/api/translated_field_type.rb +3 -3
  48. data/lib/decidim/core/test.rb +1 -0
  49. data/lib/decidim/core/test/factories.rb +21 -2
  50. data/lib/decidim/core/test/shared_examples/publicable.rb +27 -0
  51. data/lib/decidim/core/version.rb +1 -1
  52. data/lib/decidim/feature_manifest.rb +6 -6
  53. data/lib/decidim/form_builder.rb +1 -1
  54. data/lib/decidim/has_category.rb +1 -1
  55. data/lib/decidim/has_settings.rb +66 -0
  56. data/lib/decidim/manifest_registry.rb +45 -0
  57. data/lib/decidim/publicable.rb +49 -0
  58. data/lib/decidim/query_extensions.rb +1 -1
  59. data/lib/decidim/reportable.rb +3 -3
  60. data/lib/decidim/{features/settings_manifest.rb → settings_manifest.rb} +5 -5
  61. metadata +26 -33
  62. data/app/models/decidim/ability.rb +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 889376b1a7af947c4cfdd5c6182211e66a1feebb
4
- data.tar.gz: 8257ffd74960e6fe3f2ccdac75c8fbda7c67f634
3
+ metadata.gz: eb2a449a263f71206457574b6624f360c107ca44
4
+ data.tar.gz: 3f6a5a14ea188fe87e6a19e421c254c385bbde79
5
5
  SHA512:
6
- metadata.gz: 8b9c5be3cb7b7a5878fb33ba611b452e56ee998dffc1a361483858fe714c63d382b74b128d6e531f50c329c31fe5c8aee4ed9b56a873570a41bd799b026ebd3c
7
- data.tar.gz: 9c1c5e92003d02865b8b78bd31b52d13047536b9e46538ac52003f6831e9feae527ddaf12d410d948d823a02ed07ac55cd5a967f58432ff90354afb17cc47420
6
+ metadata.gz: df0da6dbd26020853ca158762a6a3cd787ef2a51fa6ed2b930ec90092170df0ed5ef7e1d65f9fe0bbbb62df978e160260cb91f81f30064f32ee7fcef34fffb32
7
+ data.tar.gz: 0a20c1fc7ca7669fcec1b0f6a544f5710817a208b0213b625ffc56cf95138fab5528b9f85480f660b9330a1d0cc8c4dd2fbe58ea107e982aec55dc04c5cd830d
@@ -3,7 +3,7 @@ $card-grid-margin-bottom: map-get($grid-column-gutter, medium);
3
3
  .card-grid{
4
4
  display: flex;
5
5
  flex-wrap: wrap;
6
-
6
+
7
7
  &:before{
8
8
  width: 0; //fixes a flexbox bug in Safari with the clearfix element
9
9
  }
@@ -18,7 +18,7 @@ $card-grid-margin-bottom: map-get($grid-column-gutter, medium);
18
18
  flex-direction: column;
19
19
  height: 100%;
20
20
  }
21
-
21
+
22
22
  .card__content{
23
23
  flex-grow: 1;
24
24
  }
@@ -70,12 +70,12 @@ $filters-padding-y: 1rem;
70
70
  padding-bottom: $filters-padding-x*1.5;
71
71
  border-bottom: none;
72
72
  }
73
-
73
+
74
74
  label{
75
75
  line-height: 1.2;
76
76
  margin-bottom: .4rem;
77
77
  }
78
-
78
+
79
79
  .button{
80
80
  margin-bottom: 0;
81
81
  }
@@ -93,4 +93,4 @@ $filters-padding-y: 1rem;
93
93
  .input-group{
94
94
  margin-bottom: 0;
95
95
  }
96
- }
96
+ }
@@ -41,10 +41,6 @@ $container-padding-2y: 2rem;
41
41
  }
42
42
  }
43
43
 
44
- .side-panel__content{
45
-
46
- }
47
-
48
44
  .side-panel__tabs{
49
45
  border: none;
50
46
  .tabs-title{
@@ -67,4 +63,4 @@ $container-padding-2y: 2rem;
67
63
  box-shadow: inset 4px 0 0 $primary;
68
64
  }
69
65
  }
70
- }
66
+ }
@@ -77,7 +77,6 @@
77
77
  font-weight: 600;
78
78
  display: flex;
79
79
  align-items: center;
80
-
81
80
 
82
81
  svg{
83
82
  margin-right: .4em;
@@ -95,4 +94,4 @@
95
94
  fill: $primary;
96
95
  }
97
96
  }
98
- }
97
+ }
@@ -29,7 +29,7 @@ module Decidim
29
29
  end
30
30
 
31
31
  def detect_current_participatory_process(params)
32
- @organization.participatory_processes.find_by_id(params["participatory_process_id"])
32
+ OrganizationParticipatoryProcesses.new(@organization).query.find_by_id(params["participatory_process_id"])
33
33
  end
34
34
  end
35
35
  end
@@ -22,7 +22,7 @@ module Decidim
22
22
  end
23
23
 
24
24
  def current_ability_klass
25
- Decidim::Ability
25
+ Decidim::Abilities::BaseAbility
26
26
  end
27
27
 
28
28
  def ability_context
@@ -30,8 +30,7 @@ module Decidim
30
30
  current_settings: try(:current_settings),
31
31
  feature_settings: try(:feature_settings),
32
32
  current_organization: try(:current_organization),
33
- current_feature: try(:current_feature),
34
- current_participatory_process: try(:current_participatory_process)
33
+ current_feature: try(:current_feature)
35
34
  }
36
35
  end
37
36
 
@@ -39,7 +39,7 @@ module Decidim
39
39
 
40
40
  def detect_participatory_process
41
41
  request.env["current_participatory_process"] ||
42
- current_organization.participatory_processes.find(params[:participatory_process_id] || params[:id])
42
+ OrganizationParticipatoryProcesses.new(current_organization).query.find(params[:participatory_process_id] || params[:id])
43
43
  end
44
44
  end
45
45
  end
@@ -5,7 +5,7 @@ require "active_support/concern"
5
5
  module Decidim
6
6
  # This concern groups methods and helpers related to accessing the settings
7
7
  # of a feature from a controller.
8
- module FeatureSettings
8
+ module Settings
9
9
  extend ActiveSupport::Concern
10
10
 
11
11
  included do
@@ -8,7 +8,7 @@ module Decidim
8
8
  class BaseController < Decidim::ApplicationController
9
9
  layout "layouts/decidim/participatory_process"
10
10
  include NeedsParticipatoryProcess
11
- include FeatureSettings
11
+ include Settings
12
12
  include ActionAuthorization
13
13
 
14
14
  helper Decidim::FiltersHelper
@@ -47,7 +47,6 @@ module Decidim
47
47
  def ability_context
48
48
  super.merge(
49
49
  current_manifest: current_manifest,
50
- current_participatory_process: current_participatory_process,
51
50
  current_settings: current_settings,
52
51
  feature_settings: feature_settings
53
52
  )
@@ -30,7 +30,7 @@ module Decidim
30
30
 
31
31
  def highlighted_participatory_processes
32
32
  @highlighted_participatory_processes ||=
33
- OrganizationParticipatoryProcesses.new(current_organization) | HighlightedParticipatoryProcesses.new
33
+ OrganizationPublishedParticipatoryProcesses.new(current_organization) | HighlightedParticipatoryProcesses.new
34
34
  end
35
35
 
36
36
  private
@@ -8,7 +8,7 @@ module Decidim
8
8
  # feature - the Feature we want to find the root path for.
9
9
  #
10
10
  # Returns a url.
11
- def feature_path(feature)
11
+ def main_feature_path(feature)
12
12
  feature_root_path_for(feature.manifest.engine, feature)
13
13
  end
14
14
 
@@ -18,6 +18,7 @@ module Decidim
18
18
  def define_abilities
19
19
  can :read, :admin_dashboard
20
20
  can :read, ParticipatoryProcess
21
+ can :read, Feature
21
22
  end
22
23
 
23
24
  def admin?
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Abilities
5
+ # Defines the abilities for a User. Intended to be used with `cancancan`.
6
+ class BaseAbility
7
+ include CanCan::Ability
8
+
9
+ # Initializes the ability class for the given user. Automatically merges
10
+ # injected abilities fmor the configuration. In order to inject more
11
+ # abilities, add this code in the `engine.rb` file of your own engine, for
12
+ # example, inside an initializer:
13
+ #
14
+ # Decidim.configure do |config|
15
+ # config.abilities << Decidim::MyEngine::Abilities::MyAbility
16
+ # end
17
+ #
18
+ # Note that, in development, this will force you to restart the server
19
+ # every time you change things in your ability classes.
20
+ #
21
+ # user - the User that needs its abilities checked.
22
+ # context - a Hash with some context related to the current request.
23
+ def initialize(user, context = {})
24
+ Decidim.abilities.each do |ability|
25
+ merge ability.constantize.new(user, context)
26
+ end
27
+
28
+ can :manage, Authorization do |authorization|
29
+ authorization.user == user
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -18,6 +18,10 @@ module Decidim
18
18
  can :read, ParticipatoryProcess do |process|
19
19
  can_manage_process?(process)
20
20
  end
21
+
22
+ can :read, Feature do |feature|
23
+ can_manage_process?(feature.participatory_process)
24
+ end
21
25
  end
22
26
  end
23
27
  end
@@ -18,6 +18,10 @@ module Decidim
18
18
  can :read, ParticipatoryProcess do |process|
19
19
  can_manage_process?(process)
20
20
  end
21
+
22
+ can :read, Feature do |feature|
23
+ can_manage_process?(feature.participatory_process)
24
+ end
21
25
  end
22
26
  end
23
27
  end
@@ -5,6 +5,9 @@ module Decidim
5
5
  # defined via a FeatureManifest. It's meant to be able to provide a single
6
6
  # feature that spans over several steps.
7
7
  class Feature < ApplicationRecord
8
+ include HasSettings
9
+ include Publicable
10
+
8
11
  belongs_to :participatory_process, foreign_key: "decidim_participatory_process_id"
9
12
  has_one :organization, through: :participatory_process
10
13
  has_many :categories, through: :participatory_process
@@ -12,31 +15,6 @@ module Decidim
12
15
 
13
16
  default_scope { order(arel_table[:weight].asc) }
14
17
 
15
- after_initialize :default_values
16
-
17
- # Public: Filters the features that are published and, therefore, visible by
18
- # the end user.
19
- #
20
- # Returns an ActiveRecord::Relation.
21
- def self.published
22
- where.not(published_at: nil)
23
- end
24
-
25
- # Public: Filters the features that are unpublished and, therefore, not visible
26
- # by the end user.
27
- #
28
- # Returns an ActiveRecord::Relation.
29
- def self.unpublished
30
- where(published_at: nil)
31
- end
32
-
33
- # Public: Finds out whether this feature is published.
34
- #
35
- # Returns true if published, false otherwise.
36
- def published?
37
- published_at.present?
38
- end
39
-
40
18
  # Public: Finds the manifest this feature is associated to.
41
19
  #
42
20
  # Returns a FeatureManifest.
@@ -53,62 +31,9 @@ module Decidim
53
31
  self.manifest_name = manifest.name
54
32
  end
55
33
 
56
- def settings
57
- settings_schema(:global).new(self[:settings]["global"])
58
- end
59
-
60
- def settings=(data)
61
- self[:settings]["global"] = serialize_settings(settings_schema(:global), data)
62
- end
63
-
64
- def default_step_settings
65
- settings_schema(:step).new(self[:settings]["default_step"])
66
- end
67
-
68
- def default_step_settings=(data)
69
- self[:settings]["default_step"] = serialize_settings(settings_schema(:step), data)
70
- end
71
-
72
- def step_settings
73
- participatory_process.steps.each_with_object({}) do |step, result|
74
- result[step.id.to_s] = settings_schema(:step).new(self[:settings].dig("steps", step.id.to_s))
75
- end
76
- end
77
-
78
- def step_settings=(data)
79
- self[:settings]["steps"] = data.each_with_object({}) do |(key, value), result|
80
- result[key.to_s] = serialize_settings(settings_schema(:step), value)
81
- end
82
- end
83
-
84
- def active_step_settings
85
- active_step = participatory_process.active_step
86
- return default_step_settings unless active_step
87
-
88
- step_settings.fetch(active_step.id.to_s)
89
- end
90
-
91
34
  # Public: Returns the value of the registered primary stat.
92
35
  def primary_stat
93
36
  @primary_stat ||= manifest.stats.filter(primary: true).with_context([self]).map { |name, value| [name, value] }.first&.last
94
37
  end
95
-
96
- private
97
-
98
- def serialize_settings(schema, value)
99
- if value.respond_to?(:attributes)
100
- value.attributes
101
- else
102
- schema.new(value)
103
- end
104
- end
105
-
106
- def settings_schema(name)
107
- manifest.settings(name.to_sym).schema
108
- end
109
-
110
- def default_values
111
- self[:settings] ||= {}
112
- end
113
38
  end
114
39
  end
@@ -7,8 +7,6 @@ module Decidim
7
7
  class Organization < ApplicationRecord
8
8
  SOCIAL_HANDLERS = [:twitter, :facebook, :instagram, :youtube, :github].freeze
9
9
 
10
- has_many :participatory_process_groups, foreign_key: "decidim_organization_id", class_name: "Decidim::ParticipatoryProcessGroup", inverse_of: :organization
11
- has_many :participatory_processes, foreign_key: "decidim_organization_id", class_name: "Decidim::ParticipatoryProcess", inverse_of: :organization
12
10
  has_many :static_pages, foreign_key: "decidim_organization_id", class_name: "Decidim::StaticPage", inverse_of: :organization
13
11
  has_many :scopes, -> { order(name: :asc) }, foreign_key: "decidim_organization_id", class_name: "Decidim::Scope", inverse_of: :organization
14
12
  has_many :admins, -> { where(admin: true) }, foreign_key: "decidim_organization_id", class_name: "Decidim::User"
@@ -8,11 +8,11 @@ module Decidim
8
8
  # active.
9
9
  class ParticipatoryProcess < ApplicationRecord
10
10
  include Decidim::HasAttachments
11
+ include Decidim::Publicable
11
12
 
12
13
  belongs_to :organization,
13
14
  foreign_key: "decidim_organization_id",
14
- class_name: "Decidim::Organization",
15
- inverse_of: :participatory_processes
15
+ class_name: "Decidim::Organization"
16
16
  belongs_to :participatory_process_group,
17
17
  foreign_key: "decidim_participatory_process_group_id",
18
18
  class_name: "Decidim::ParticipatoryProcessGroup",
@@ -50,13 +50,6 @@ module Decidim
50
50
  mount_uploader :hero_image, Decidim::HeroImageUploader
51
51
  mount_uploader :banner_image, Decidim::BannerImageUploader
52
52
 
53
- # Scope to return only the published processes.
54
- #
55
- # Returns an ActiveRecord::Relation.
56
- def self.published
57
- where.not(published_at: nil)
58
- end
59
-
60
53
  # Scope to return only the promoted processes.
61
54
  #
62
55
  # Returns an ActiveRecord::Relation.
@@ -64,13 +57,6 @@ module Decidim
64
57
  where(promoted: true)
65
58
  end
66
59
 
67
- # Checks whether the process has been published or not.
68
- #
69
- # Returns a boolean.
70
- def published?
71
- published_at.present?
72
- end
73
-
74
60
  def hashtag
75
61
  attributes["hashtag"].to_s.delete("#")
76
62
  end
@@ -8,8 +8,7 @@ module Decidim
8
8
  inverse_of: :participatory_process_group
9
9
  belongs_to :organization,
10
10
  foreign_key: "decidim_organization_id",
11
- class_name: "Decidim::Organization",
12
- inverse_of: :participatory_process_groups
11
+ class_name: "Decidim::Organization"
13
12
 
14
13
  mount_uploader :hero_image, Decidim::HeroImageUploader
15
14
  end
@@ -9,5 +9,14 @@ module Decidim
9
9
 
10
10
  ROLES = %w(admin collaborator moderator).freeze
11
11
  validates :role, inclusion: { in: ROLES }, uniqueness: { scope: [:user, :participatory_process] }
12
+ validate :user_and_participatory_process_same_organization
13
+
14
+ private
15
+
16
+ # Private: check if the process and the user have the same organization
17
+ def user_and_participatory_process_same_organization
18
+ return if !participatory_process || !user
19
+ errors.add(:participatory_process, :invalid) unless user.organization == participatory_process.organization
20
+ end
12
21
  end
13
22
  end
@@ -33,13 +33,6 @@ module Decidim
33
33
  # Returns a String.
34
34
  attr_accessor :invitation_instructions
35
35
 
36
- delegate :can?, to: :ability
37
-
38
- # Gets the ability instance for the given user.
39
- def ability
40
- @ability ||= Ability.new(self)
41
- end
42
-
43
36
  # Public: returns the user's name or the default one
44
37
  def name
45
38
  super || I18n.t("decidim.anonymous_user")
@@ -75,7 +75,7 @@ module Decidim
75
75
  end
76
76
 
77
77
  def published_features
78
- @published_features ||= Feature.where(participatory_process: organization.participatory_processes.published).published
78
+ @published_features ||= Feature.where(participatory_process: OrganizationPublishedParticipatoryProcesses.new(organization).query).published
79
79
  end
80
80
  end
81
81
  end