decidim 0.0.1.alpha4 → 0.0.1.alpha5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of decidim might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.codeclimate.yml +1 -0
- data/.gitignore +2 -0
- data/.travis.yml +2 -1
- data/Dockerfile +1 -12
- data/Gemfile +8 -3
- data/Gemfile.common +1 -0
- data/Gemfile.lock +49 -38
- data/README.md +1 -0
- data/decidim-admin/Gemfile +3 -14
- data/decidim-admin/Rakefile +0 -5
- data/decidim-admin/app/assets/javascripts/decidim/admin.js +4 -3
- data/decidim-admin/app/commands/decidim/admin/create_participatory_process.rb +47 -0
- data/decidim-admin/app/commands/decidim/admin/update_participatory_process.rb +49 -0
- data/decidim-admin/app/controllers/concerns/decidim/needs_authorization.rb +50 -0
- data/decidim-admin/app/controllers/decidim/admin/application_controller.rb +2 -0
- data/decidim-admin/app/controllers/decidim/admin/dashboard_controller.rb +11 -0
- data/decidim-admin/app/controllers/decidim/admin/participatory_processes_controller.rb +85 -0
- data/decidim-admin/app/forms/decidim/admin/participatory_process_form.rb +37 -0
- data/decidim-admin/app/helpers/decidim/admin/application_helper.rb +2 -0
- data/decidim-admin/app/helpers/decidim/admin/attributes_display_helper.rb +62 -0
- data/decidim-admin/app/policies/decidim/admin/dashboard_policy.rb +15 -0
- data/decidim-admin/app/policies/decidim/admin/participatory_process_policy.rb +57 -0
- data/decidim-admin/app/views/decidim/admin/participatory_processes/_form.html.erb +23 -0
- data/decidim-admin/app/views/decidim/admin/participatory_processes/edit.html.erb +11 -0
- data/decidim-admin/app/views/decidim/admin/participatory_processes/index.html.erb +34 -0
- data/decidim-admin/app/views/decidim/admin/participatory_processes/new.html.erb +11 -0
- data/decidim-admin/app/views/decidim/admin/participatory_processes/show.html.erb +20 -0
- data/decidim-admin/app/views/layouts/decidim/admin/_sidebar.html.erb +1 -0
- data/decidim-admin/config/locales/ca.yml +40 -0
- data/decidim-admin/config/locales/en.yml +32 -0
- data/decidim-admin/config/locales/es.yml +40 -0
- data/decidim-admin/config/routes.rb +4 -1
- data/decidim-admin/decidim-admin.gemspec +1 -2
- data/decidim-admin/lib/decidim/admin/engine.rb +1 -1
- data/decidim-admin/spec/features/admin_invite_spec.rb +2 -6
- data/decidim-admin/spec/features/manage_participatory_processes_spec.rb +127 -0
- data/decidim-admin/spec/policies/dashboard_policy_spec.rb +23 -0
- data/decidim-admin/spec/policies/participatory_process_policy_spec.rb +153 -0
- data/decidim-dev/Gemfile +3 -14
- data/decidim-dev/decidim-dev.gemspec +2 -3
- data/decidim-dev/lib/decidim/test/i18n_spec.rb +16 -0
- data/decidim-dev/lib/decidim/test/rspec_support/action_mailer.rb +3 -2
- data/decidim-dev/lib/decidim/test/rspec_support/warden.rb +1 -0
- data/decidim-system/Gemfile +3 -14
- data/decidim-system/Rakefile +0 -5
- data/decidim-system/app/assets/javascripts/decidim/system.js +4 -3
- data/decidim-system/app/commands/decidim/system/register_organization.rb +1 -0
- data/decidim-system/app/forms/decidim/system/register_organization_form.rb +2 -1
- data/decidim-system/app/views/decidim/system/organizations/new.html.erb +4 -0
- data/decidim-system/config/locales/ca.yml +60 -0
- data/decidim-system/config/locales/es.yml +60 -0
- data/decidim-system/decidim-system.gemspec +1 -2
- data/decidim-system/lib/decidim/system/engine.rb +0 -1
- data/decidim-system/spec/commands/decidim/system/register_organization_spec.rb +1 -0
- data/decidim-system/spec/features/organizations_spec.rb +1 -0
- data/decidim.gemspec +1 -0
- data/lib/generators/decidim/templates/Gemfile.erb +0 -11
- metadata +43 -12
- data/common_gemfile.rb +0 -12
- data/decidim-admin/Gemfile.lock +0 -383
- data/decidim-dev/Gemfile.lock +0 -381
- data/decidim-system/Gemfile.lock +0 -377
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
# Shared behaviour for controllers that need authorization to work.
|
7
|
+
module NeedsAuthorization
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
include Pundit
|
12
|
+
after_action :verify_authorized
|
13
|
+
|
14
|
+
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Overwrites the `policy` method from the `pundit` gem in order to be
|
19
|
+
# able to specify which policy class should be used in each case. This is
|
20
|
+
# due to `pundit` failing to correctly identify the policy class when the
|
21
|
+
# model class name is scoped and the policy class is in a different scope
|
22
|
+
# (eg. `Decidim::ParticipatoryProcess` and
|
23
|
+
# `Decidim::Admin::ParticipatoryProcessPolicy`). The original method does
|
24
|
+
# not let us specify the correct class.
|
25
|
+
#
|
26
|
+
# Remember that, in order to make this work, you'll need to define the
|
27
|
+
# `policy_class` method in the controller, which should only return a
|
28
|
+
# policy class name.
|
29
|
+
#
|
30
|
+
# record - the record that will be evaluated against the policy class.
|
31
|
+
def policy(record)
|
32
|
+
policies[record] ||= policy_class.new(current_user, record)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Needed in order to make the `policy` method work. Overwirite it in the
|
36
|
+
# given controller and make it return a Policy class.
|
37
|
+
def policy_class
|
38
|
+
raise NotImplementedError, "Define this method and make it return a policy class name in order to make it work"
|
39
|
+
end
|
40
|
+
|
41
|
+
# Handles the case when a user visits a path that is not allowed to them.
|
42
|
+
# Redirects the user to the root path and shows a flash message telling
|
43
|
+
# them they are not authorized.
|
44
|
+
def user_not_authorized
|
45
|
+
flash[:alert] = t("actions.unauthorized", scope: "decidim.admin")
|
46
|
+
redirect_to(request.referrer || decidim_admin.root_path)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -3,7 +3,18 @@ require_dependency "decidim/admin/application_controller"
|
|
3
3
|
|
4
4
|
module Decidim
|
5
5
|
module Admin
|
6
|
+
# Controller that shows a simple dashboard.
|
7
|
+
#
|
6
8
|
class DashboardController < ApplicationController
|
9
|
+
def show
|
10
|
+
authorize :dashboard
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def policy_class
|
16
|
+
Decidim::Admin::DashboardPolicy
|
17
|
+
end
|
7
18
|
end
|
8
19
|
end
|
9
20
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_dependency "decidim/admin/application_controller"
|
3
|
+
|
4
|
+
module Decidim
|
5
|
+
module Admin
|
6
|
+
# Controller that allows managing all the Admins.
|
7
|
+
#
|
8
|
+
class ParticipatoryProcessesController < ApplicationController
|
9
|
+
def index
|
10
|
+
@participatory_processes = collection
|
11
|
+
authorize @participatory_processes
|
12
|
+
end
|
13
|
+
|
14
|
+
def new
|
15
|
+
@form = ParticipatoryProcessForm.new
|
16
|
+
authorize ParticipatoryProcess
|
17
|
+
end
|
18
|
+
|
19
|
+
def create
|
20
|
+
@form = ParticipatoryProcessForm.from_params(params)
|
21
|
+
authorize ParticipatoryProcess
|
22
|
+
|
23
|
+
CreateParticipatoryProcess.call(@form, current_organization) do
|
24
|
+
on(:ok) do
|
25
|
+
flash[:notice] = I18n.t("participatory_processes.create.success", scope: "decidim.admin")
|
26
|
+
redirect_to participatory_processes_path
|
27
|
+
end
|
28
|
+
|
29
|
+
on(:invalid) do
|
30
|
+
flash.now[:alert] = I18n.t("participatory_processes.create.error", scope: "decidim.admin")
|
31
|
+
render :new
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def edit
|
37
|
+
@participatory_process = collection.find(params[:id])
|
38
|
+
authorize @participatory_process
|
39
|
+
@form = ParticipatoryProcessForm.from_model(@participatory_process)
|
40
|
+
end
|
41
|
+
|
42
|
+
def update
|
43
|
+
@participatory_process = collection.find(params[:id])
|
44
|
+
authorize @participatory_process
|
45
|
+
@form = ParticipatoryProcessForm.from_params(params)
|
46
|
+
|
47
|
+
UpdateParticipatoryProcess.call(@participatory_process, @form) do
|
48
|
+
on(:ok) do
|
49
|
+
flash[:notice] = I18n.t("participatory_processes.update.success", scope: "decidim.admin")
|
50
|
+
redirect_to participatory_processes_path
|
51
|
+
end
|
52
|
+
|
53
|
+
on(:invalid) do
|
54
|
+
flash.now[:alert] = I18n.t("participatory_processes.update.error", scope: "decidim.admin")
|
55
|
+
render :edit
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def show
|
61
|
+
@participatory_process = collection.find(params[:id])
|
62
|
+
authorize @participatory_process
|
63
|
+
end
|
64
|
+
|
65
|
+
def destroy
|
66
|
+
@participatory_process = collection.find(params[:id]).destroy!
|
67
|
+
authorize @participatory_process
|
68
|
+
|
69
|
+
flash[:notice] = I18n.t("participatory_processes.destroy.success", scope: "decidim.admin")
|
70
|
+
|
71
|
+
redirect_to participatory_processes_path
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def collection
|
77
|
+
current_organization.participatory_processes
|
78
|
+
end
|
79
|
+
|
80
|
+
def policy_class
|
81
|
+
Decidim::Admin::ParticipatoryProcessPolicy
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Decidim
|
3
|
+
module Admin
|
4
|
+
# A form object used to create participatory processes from the admin
|
5
|
+
# dashboard.
|
6
|
+
#
|
7
|
+
class ParticipatoryProcessForm < Rectify::Form
|
8
|
+
include TranslatableAttributes
|
9
|
+
|
10
|
+
translatable_attribute :title, String
|
11
|
+
translatable_attribute :subtitle, String
|
12
|
+
translatable_attribute :description, String
|
13
|
+
translatable_attribute :short_description, String
|
14
|
+
|
15
|
+
mimic :participatory_process
|
16
|
+
|
17
|
+
attribute :slug, String
|
18
|
+
attribute :hashtag, String
|
19
|
+
|
20
|
+
validates :slug, presence: true
|
21
|
+
translatable_validates :title, :subtitle, :description, :short_description, presence: true
|
22
|
+
|
23
|
+
validate :slug, :slug_uniqueness
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def slug_uniqueness
|
28
|
+
return unless ParticipatoryProcess.where(slug: slug).where.not(id: id).any?
|
29
|
+
|
30
|
+
errors.add(
|
31
|
+
:slug,
|
32
|
+
I18n.t("models.participatory_process.validations.slug_uniqueness", scope: "decidim.admin")
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Decidim
|
3
|
+
module Admin
|
4
|
+
# Custom helpers, scoped to the admin panel.
|
5
|
+
#
|
6
|
+
module AttributesDisplayHelper
|
7
|
+
# Displays the given attributes list in a list. This is a simple
|
8
|
+
# `show_for` alternative, so there's no way to modify how an attribute is
|
9
|
+
# shown and there is no intention on adding this. It is intnded to be
|
10
|
+
# used inside a `dl` HTML tag, so you can customize how a specific
|
11
|
+
# attribute has to be shown directly:
|
12
|
+
#
|
13
|
+
# <dl>
|
14
|
+
# <%= display_for @post, :title, :body %>
|
15
|
+
# <dt>Comments number</dt>
|
16
|
+
# <dd>2</dd>
|
17
|
+
# </dl>
|
18
|
+
#
|
19
|
+
# This will render this HTML:
|
20
|
+
#
|
21
|
+
# <dl>
|
22
|
+
# <dt>Title</dt>
|
23
|
+
# <dd>Hello, world!</dd>
|
24
|
+
# <dt>Body</dt>
|
25
|
+
# <dd>Lorem ipsum dolor sit amet...</dd>
|
26
|
+
# <dt>Comments number</dt>
|
27
|
+
# <dd>2</dd>
|
28
|
+
# </dl>
|
29
|
+
#
|
30
|
+
# record - any Ruby object that needs some attributes rendered
|
31
|
+
# attrs - a list of N attributes of the `record`.
|
32
|
+
def display_for(record, *attrs)
|
33
|
+
attrs.map do |attr|
|
34
|
+
if record.column_for_attribute(attr).type == :hstore
|
35
|
+
I18n.available_locales.map do |locale|
|
36
|
+
content_tag(:dt, record.class.human_attribute_name(attr) + " (#{locale})") +
|
37
|
+
display_value(record, attr, locale)
|
38
|
+
end.reduce(:+)
|
39
|
+
else
|
40
|
+
display_label(record, attr) + display_value(record, attr)
|
41
|
+
end
|
42
|
+
end.reduce(:+)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Private: Holds the logic to render a label for a given attribute.
|
48
|
+
def display_label(record, attr)
|
49
|
+
content_tag(:dt, record.class.human_attribute_name(attr))
|
50
|
+
end
|
51
|
+
|
52
|
+
# Private: Holds the logic to render the attribute value.
|
53
|
+
def display_value(record, attr, locale = nil)
|
54
|
+
return I18n.with_locale(locale) do
|
55
|
+
content_tag(:dd, translated_attribute(record.send(attr)).try(:html_safe))
|
56
|
+
end if locale
|
57
|
+
|
58
|
+
content_tag(:dd, record.send(attr).try(:html_safe))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Decidim
|
3
|
+
module Admin
|
4
|
+
# A policy to define all the authorizations regarding a
|
5
|
+
# ParticipatoryProcess, to be used with Pundit.
|
6
|
+
class DashboardPolicy < ApplicationPolicy
|
7
|
+
# Checks if the user can see the admin dashboard.
|
8
|
+
#
|
9
|
+
# Returns a Boolean.
|
10
|
+
def show?
|
11
|
+
user.roles.include?("admin")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Decidim
|
3
|
+
module Admin
|
4
|
+
# A policy to define all the authorizations regarding a
|
5
|
+
# ParticipatoryProcess, to be used with Pundit.
|
6
|
+
class ParticipatoryProcessPolicy < ApplicationPolicy
|
7
|
+
# Checks if the user can see the form for participatory process creation.
|
8
|
+
#
|
9
|
+
# Returns a Boolean.
|
10
|
+
def new?
|
11
|
+
user.roles.include?("admin")
|
12
|
+
end
|
13
|
+
|
14
|
+
# Checks if the user can create a participatory process.
|
15
|
+
#
|
16
|
+
# Returns a Boolean.
|
17
|
+
def create?
|
18
|
+
user.roles.include?("admin")
|
19
|
+
end
|
20
|
+
|
21
|
+
# Checks if the user can list a participatory process.
|
22
|
+
#
|
23
|
+
# Returns a Boolean.
|
24
|
+
def index?
|
25
|
+
user.roles.include?("admin") && user.organization == record.first.organization
|
26
|
+
end
|
27
|
+
|
28
|
+
# Checks if the user can see a participatory process.
|
29
|
+
#
|
30
|
+
# Returns a Boolean.
|
31
|
+
def show?
|
32
|
+
user.roles.include?("admin") && user.organization == record.organization
|
33
|
+
end
|
34
|
+
|
35
|
+
# Checks if the user can edit a participatory process.
|
36
|
+
#
|
37
|
+
# Returns a Boolean.
|
38
|
+
def edit?
|
39
|
+
user.roles.include?("admin") && user.organization == record.organization
|
40
|
+
end
|
41
|
+
|
42
|
+
# Checks if the user can update a participatory process.
|
43
|
+
#
|
44
|
+
# Returns a Boolean.
|
45
|
+
def update?
|
46
|
+
user.roles.include?("admin") && user.organization == record.organization
|
47
|
+
end
|
48
|
+
|
49
|
+
# Checks if the user can destroy a participatory process.
|
50
|
+
#
|
51
|
+
# Returns a Boolean.
|
52
|
+
def destroy?
|
53
|
+
user.roles.include?("admin") && user.organization == record.organization
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<div class="field">
|
2
|
+
<%= form.translated :text_field, :title, autofocus: true %>
|
3
|
+
</div>
|
4
|
+
|
5
|
+
<div class="field">
|
6
|
+
<%= form.translated :text_field, :subtitle %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="field">
|
10
|
+
<%= form.text_field :slug %>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<div class="field">
|
14
|
+
<%= form.text_field :hashtag %>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div class="field">
|
18
|
+
<%= form.translated :text_area, :short_description %>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div class="field">
|
22
|
+
<%= form.translated :text_area, :description %>
|
23
|
+
</div>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<% content_for :title do %>
|
2
|
+
<h2><%= t "decidim.admin.titles.participatory_processes" %></h2>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<div class="actions title">
|
6
|
+
<%= link_to t("actions.new", scope: "decidim.admin", name: t("models.participatory_process.name", scope: "decidim.admin")), ['new', 'participatory_process'], class: 'new' %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<table class="stack">
|
10
|
+
<thead>
|
11
|
+
<tr>
|
12
|
+
<th><%= t("models.participatory_process.fields.title", scope: "decidim.admin") %></th>
|
13
|
+
<th><%= t("models.participatory_process.fields.created_at", scope: "decidim.admin") %></th>
|
14
|
+
<th class="actions"><%= t("actions.title", scope: "decidim.admin") %></th>
|
15
|
+
</tr>
|
16
|
+
</thead>
|
17
|
+
<tbody>
|
18
|
+
<% @participatory_processes.each do |process| %>
|
19
|
+
<tr>
|
20
|
+
<td>
|
21
|
+
<%= link_to translated_attribute(process.title), process %><br />
|
22
|
+
</td>
|
23
|
+
<td>
|
24
|
+
<%= l process.created_at, format: :short %>
|
25
|
+
</td>
|
26
|
+
<td class="actions">
|
27
|
+
<%= link_to_if policy(process).edit?, t("actions.edit", scope: "decidim.admin"), ['edit', process] %>
|
28
|
+
|
29
|
+
<%= link_to_if policy(process).destroy?, t("actions.destroy", scope: "decidim.admin"), process, method: :delete, class: "small alert button", data: { confirm: t("actions.confirm_destroy", scope: "decidim.admin") } %>
|
30
|
+
</td>
|
31
|
+
</tr>
|
32
|
+
<% end %>
|
33
|
+
</tbody>
|
34
|
+
</table>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<% content_for :title do %>
|
2
|
+
<h2><%= link_to translated_attribute(@participatory_process.title), @participatory_process %></h2>
|
3
|
+
<h3 class="subheader"><%= translated_attribute(@participatory_process.subtitle) %></h3>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<div class="actions">
|
7
|
+
<hr />
|
8
|
+
<%= link_to_if policy(@participatory_process).edit?, t("decidim.admin.actions.edit"), ['edit', @participatory_process] %>
|
9
|
+
<%= link_to_if policy(@participatory_process).destroy?, t("decidim.admin.actions.destroy"), @participatory_process, method: :delete, class: "alert button", data: { confirm: t("decidim.admin.actions.confirm_destroy") } %>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<dl>
|
13
|
+
<%= display_for @participatory_process,
|
14
|
+
:title,
|
15
|
+
:subtitle,
|
16
|
+
:hashtag,
|
17
|
+
:short_description,
|
18
|
+
:description
|
19
|
+
%>
|
20
|
+
</dl>
|