decidim-action_delegator 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +225 -0
- data/Rakefile +41 -0
- data/app/assets/config/admin/decidim_action_delegator_manifest.css +0 -0
- data/app/assets/config/admin/decidim_action_delegator_manifest.js +1 -0
- data/app/assets/config/decidim_action_delegator_manifest.css +3 -0
- data/app/assets/config/decidim_action_delegator_manifest.js +2 -0
- data/app/assets/images/decidim/action_delegator/icon.svg +1 -0
- data/app/assets/javascripts/decidim/action_delegator/admin/action_delegator.js.es6 +3 -0
- data/app/assets/javascripts/decidim/action_delegator/questions.js.es6 +26 -0
- data/app/assets/stylesheets/decidim/action_delegator/questions.scss +25 -0
- data/app/commands/decidim/action_delegator/admin/create_delegation.rb +62 -0
- data/app/commands/decidim/action_delegator/consultations/multiple_vote_question_override.rb +31 -0
- data/app/commands/decidim/action_delegator/consultations/vote_question_override.rb +36 -0
- data/app/commands/decidim/action_delegator/vote_delegation.rb +28 -0
- data/app/controllers/concerns/decidim/action_delegator/admin/filterable.rb +23 -0
- data/app/controllers/decidim/action_delegator/admin/application_controller.rb +19 -0
- data/app/controllers/decidim/action_delegator/admin/consultations/exports_controller.rb +27 -0
- data/app/controllers/decidim/action_delegator/admin/consultations_controller.rb +33 -0
- data/app/controllers/decidim/action_delegator/admin/delegations_controller.rb +79 -0
- data/app/controllers/decidim/action_delegator/admin/exports/sum_of_weights_controller.rb +15 -0
- data/app/controllers/decidim/action_delegator/admin/results/sum_of_weights_controller.rb +37 -0
- data/app/controllers/decidim/action_delegator/admin/settings_controller.rb +71 -0
- data/app/controllers/decidim/action_delegator/application_controller.rb +14 -0
- data/app/controllers/decidim/action_delegator/consultations/question_multiple_votes_controller_override.rb +28 -0
- data/app/controllers/decidim/action_delegator/consultations/question_votes_controller_override.rb +55 -0
- data/app/controllers/decidim/action_delegator/user_delegations_controller.rb +22 -0
- data/app/controllers/decidim/action_delegator/verifications/sms/authorizations_controller_override.rb +38 -0
- data/app/forms/decidim/action_delegator/admin/delegation_form.rb +25 -0
- data/app/forms/decidim/action_delegator/consultations/vote_form_override.rb +15 -0
- data/app/helpers/decidim/action_delegator/admin/delegation_helper.rb +27 -0
- data/app/helpers/decidim/action_delegator/application_helper.rb +10 -0
- data/app/jobs/decidim/action_delegator/export_consultation_results_job.rb +51 -0
- data/app/jobs/decidim/action_delegator/send_sms_job.rb +60 -0
- data/app/jobs/decidim/action_delegator/twilio_send_sms_job.rb +43 -0
- data/app/models/decidim/action_delegator/application_record.rb +10 -0
- data/app/models/decidim/action_delegator/consultations/vote_override.rb +15 -0
- data/app/models/decidim/action_delegator/delegation.rb +26 -0
- data/app/models/decidim/action_delegator/setting.rb +22 -0
- data/app/models/decidim/action_delegator/unversioned_vote.rb +19 -0
- data/app/models/decidim/action_delegator/whodunnit_vote.rb +28 -0
- data/app/permissions/decidim/action_delegator/consultations_permissions_extension.rb +27 -0
- data/app/permissions/decidim/action_delegator/permissions.rb +74 -0
- data/app/presenters/decidim/action_delegator/admin/consultation_presenter.rb +15 -0
- data/app/presenters/decidim/action_delegator/admin/setting_presenter.rb +13 -0
- data/app/presenters/decidim/action_delegator/question_with_totals.rb +24 -0
- data/app/queries/decidim/action_delegator/consultation_delegations.rb +25 -0
- data/app/queries/decidim/action_delegator/decrypted_authorizations.rb +112 -0
- data/app/queries/decidim/action_delegator/delegated_votes_versions.rb +31 -0
- data/app/queries/decidim/action_delegator/delegates_votes_by_consultation.rb +24 -0
- data/app/queries/decidim/action_delegator/delegates_votes_by_question.rb +26 -0
- data/app/queries/decidim/action_delegator/delegation_votes.rb +30 -0
- data/app/queries/decidim/action_delegator/grantee_delegations.rb +24 -0
- data/app/queries/decidim/action_delegator/json_build_object_query.rb +45 -0
- data/app/queries/decidim/action_delegator/organization_delegations.rb +26 -0
- data/app/queries/decidim/action_delegator/organization_settings.rb +25 -0
- data/app/queries/decidim/action_delegator/published_responses.rb +25 -0
- data/app/queries/decidim/action_delegator/responses_by_membership.rb +75 -0
- data/app/queries/decidim/action_delegator/scrutiny.rb +87 -0
- data/app/queries/decidim/action_delegator/setting_delegations.rb +19 -0
- data/app/queries/decidim/action_delegator/sum_of_membership_weight.rb +48 -0
- data/app/queries/decidim/action_delegator/sum_of_weights.rb +25 -0
- data/app/queries/decidim/action_delegator/type_and_weight.rb +26 -0
- data/app/queries/decidim/action_delegator/voted_with_direct_verification.rb +53 -0
- data/app/queries/decidim/action_delegator/votes_count_aggregation.rb +34 -0
- data/app/serializers/decidim/action_delegator/consultation_results_serializer.rb +19 -0
- data/app/serializers/decidim/action_delegator/sum_of_weights_serializer.rb +17 -0
- data/app/services/decidim/action_delegator/sms_gateway.rb +51 -0
- data/app/views/decidim/action_delegator/_callout.html.erb +5 -0
- data/app/views/decidim/action_delegator/_delegations_modal.html.erb +93 -0
- data/app/views/decidim/action_delegator/_link_to_delegations.html.erb +5 -0
- data/app/views/decidim/action_delegator/_link_to_question.html.erb +5 -0
- data/app/views/decidim/action_delegator/admin/consultations/results.html.erb +62 -0
- data/app/views/decidim/action_delegator/admin/delegations/index.html.erb +36 -0
- data/app/views/decidim/action_delegator/admin/delegations/new.html.erb +30 -0
- data/app/views/decidim/action_delegator/admin/results/sum_of_weights/index.html.erb +63 -0
- data/app/views/decidim/action_delegator/admin/settings/index.html.erb +39 -0
- data/app/views/decidim/action_delegator/admin/settings/new.html.erb +30 -0
- data/app/views/decidim/action_delegator/user_delegations/index.html.erb +19 -0
- data/app/views/decidim/consultations/consultations/_question.html.erb +41 -0
- data/app/views/decidim/consultations/consultations/show.html.erb +14 -0
- data/app/views/decidim/consultations/question_multiple_votes/_form.html.erb +25 -0
- data/app/views/decidim/consultations/question_votes/update_vote_button.js.erb +32 -0
- data/app/views/decidim/consultations/questions/_vote_button.html.erb +107 -0
- data/app/views/decidim/consultations/questions/_vote_modal.html.erb +30 -0
- data/app/views/decidim/consultations/questions/_vote_modal_confirm.html.erb +38 -0
- data/app/views/decidim/verifications/sms/authorizations/new.html.erb +33 -0
- data/app/views/layouts/decidim/action_delegator/admin/_users_sidebar.html.erb +56 -0
- data/app/views/layouts/decidim/action_delegator/admin/delegations.html.erb +13 -0
- data/app/views/layouts/decidim/admin/consultation.html.erb +56 -0
- data/app/views/layouts/decidim/admin/question.html.erb +98 -0
- data/app/views/layouts/decidim/admin/users.html.erb +7 -0
- data/config/i18n-tasks.yml +10 -0
- data/config/locales/ca.yml +101 -0
- data/config/locales/cs.yml +101 -0
- data/config/locales/en.yml +109 -0
- data/config/locales/es.yml +101 -0
- data/db/migrate/20200729194540_create_decidim_action_delegator_delegations.rb +12 -0
- data/db/migrate/20200824113801_create_settings.rb +13 -0
- data/db/migrate/20200828113755_add_setting_id_to_delegations.rb +11 -0
- data/db/migrate/20200831141540_make_granter_id_and_grantee_id_non_nullable.rb +8 -0
- data/db/migrate/20201001172345_remove_expires_at_from_delegations.rb +7 -0
- data/db/migrate/20201005203554_add_setting_granter_unique_index_to_delegations.rb +10 -0
- data/db/migrate/20201006084522_remove_setting_id_index_from_delegations.rb +7 -0
- data/db/migrate/20201030164808_add_delegation_id_to_versions.rb +8 -0
- data/db/seeds.rb +7 -0
- data/lib/decidim/action_delegator/admin.rb +10 -0
- data/lib/decidim/action_delegator/admin_engine.rb +42 -0
- data/lib/decidim/action_delegator/engine.rb +53 -0
- data/lib/decidim/action_delegator/test/factories.rb +25 -0
- data/lib/decidim/action_delegator/version.rb +10 -0
- data/lib/decidim/action_delegator.rb +29 -0
- data/lib/json_key.rb +10 -0
- metadata +267 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
module Admin
|
6
|
+
module Results
|
7
|
+
class SumOfWeightsController < Decidim::Consultations::Admin::ConsultationsController
|
8
|
+
def index
|
9
|
+
params[:slug] = params[:consultation_slug]
|
10
|
+
|
11
|
+
enforce_permission_to :read, :consultation, consultation: current_consultation
|
12
|
+
|
13
|
+
@questions = Scrutiny.new(current_consultation).questions
|
14
|
+
@responses = responses.group_by(&:question_id)
|
15
|
+
@total_delegates = DelegatesVotesByConsultation.new(current_consultation).query
|
16
|
+
|
17
|
+
render layout: "decidim/admin/consultation"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def permission_class_chain
|
23
|
+
Decidim.permissions_registry.chain_for(ActionDelegator::Admin::ApplicationController)
|
24
|
+
end
|
25
|
+
|
26
|
+
def questions
|
27
|
+
current_consultation.questions.published.includes(:responses)
|
28
|
+
end
|
29
|
+
|
30
|
+
def responses
|
31
|
+
SumOfWeights.new(current_consultation).query
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
module Admin
|
6
|
+
class SettingsController < ActionDelegator::Admin::ApplicationController
|
7
|
+
helper DelegationHelper
|
8
|
+
include Filterable
|
9
|
+
|
10
|
+
layout "decidim/admin/users"
|
11
|
+
|
12
|
+
def index
|
13
|
+
enforce_permission_to :index, :setting
|
14
|
+
|
15
|
+
@settings = filtered_collection.map do |setting|
|
16
|
+
SettingPresenter.new(setting)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def new
|
21
|
+
enforce_permission_to :create, :setting
|
22
|
+
|
23
|
+
@setting = Setting.new(max_grants: 1)
|
24
|
+
end
|
25
|
+
|
26
|
+
def create
|
27
|
+
enforce_permission_to :create, :setting
|
28
|
+
|
29
|
+
@setting = build_setting
|
30
|
+
|
31
|
+
if @setting.save
|
32
|
+
flash[:notice] = I18n.t("settings.create.success", scope: "decidim.action_delegator.admin")
|
33
|
+
redirect_to decidim_admin_action_delegator.settings_path
|
34
|
+
else
|
35
|
+
flash.now[:error] = I18n.t("settings.create.error", scope: "decidim.action_delegator.admin")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def destroy
|
40
|
+
enforce_permission_to :destroy, :setting, resource: setting
|
41
|
+
|
42
|
+
if setting.destroy
|
43
|
+
flash[:notice] = I18n.t("settings.destroy.success", scope: "decidim.action_delegator.admin")
|
44
|
+
else
|
45
|
+
flash[:error] = I18n.t("settings.destroy.error", scope: "decidim.action_delegator.admin")
|
46
|
+
end
|
47
|
+
|
48
|
+
redirect_to settings_path
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def setting_params
|
54
|
+
params.require(:setting).permit(:max_grants, :decidim_consultation_id)
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_setting
|
58
|
+
Setting.new(setting_params)
|
59
|
+
end
|
60
|
+
|
61
|
+
def setting
|
62
|
+
@setting ||= collection.find_by(id: params[:id])
|
63
|
+
end
|
64
|
+
|
65
|
+
def collection
|
66
|
+
@collection ||= ActionDelegator::OrganizationSettings.new(current_organization).query
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
# This controller is the abstract class from which all other controllers of
|
6
|
+
# this engine inherit.
|
7
|
+
#
|
8
|
+
class ApplicationController < Decidim::ApplicationController
|
9
|
+
# def permission_class_chain
|
10
|
+
# [::Decidim::ActionDelegator::Permissions] + super
|
11
|
+
# end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
module Consultations
|
6
|
+
module QuestionMultipleVotesControllerOverride
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
helper_method :delegation
|
11
|
+
before_action do
|
12
|
+
session[:delegation_id] = params[:delegation] if params[:delegation]
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def delegation
|
18
|
+
@delegation ||= Decidim::ActionDelegator::Delegation.find_by(id: delegation_id)
|
19
|
+
end
|
20
|
+
|
21
|
+
def delegation_id
|
22
|
+
@delegation_id ||= params[:decidim_consultations_delegation_id] || params[:delegation] || session[:delegation_id]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/app/controllers/decidim/action_delegator/consultations/question_votes_controller_override.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
module Consultations
|
6
|
+
module QuestionVotesControllerOverride
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
def destroy
|
11
|
+
enforce_permission_to_unvote
|
12
|
+
|
13
|
+
user = delegation.blank? ? current_user : delegation.granter
|
14
|
+
|
15
|
+
PaperTrail.request(enabled: delegation.present?, whodunnit: current_user.id) do
|
16
|
+
Decidim::Consultations::UnvoteQuestion.call(current_question, user) do
|
17
|
+
on(:ok) do
|
18
|
+
current_question.reload
|
19
|
+
render :update_vote_button
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def info_for_paper_trail
|
28
|
+
if delegation.present?
|
29
|
+
{ decidim_action_delegator_delegation_id: delegation.id }
|
30
|
+
else
|
31
|
+
{}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def delegation
|
36
|
+
@delegation ||= Decidim::ActionDelegator::Delegation.find_by(id: params[:decidim_consultations_delegation_id])
|
37
|
+
end
|
38
|
+
|
39
|
+
def enforce_permission_to_unvote
|
40
|
+
if delegation.blank?
|
41
|
+
enforce_permission_to :unvote, :question, question: current_question
|
42
|
+
else
|
43
|
+
raise Decidim::ActionForbidden unless allowed_to?(
|
44
|
+
:unvote_delegation,
|
45
|
+
:question,
|
46
|
+
{ question: current_question, delegation: delegation },
|
47
|
+
[Decidim::ActionDelegator::Permissions, Decidim::Admin::Permissions, Decidim::Permissions]
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
# This controller handles user profile actions for this module
|
6
|
+
class UserDelegationsController < ActionDelegator::ApplicationController
|
7
|
+
include Decidim::UserProfile
|
8
|
+
|
9
|
+
helper_method :delegations
|
10
|
+
|
11
|
+
def index
|
12
|
+
enforce_permission_to :read, :user, current_user: current_user
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def delegations
|
18
|
+
@delegations ||= Delegation.where(grantee_id: current_user.id)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
module Verifications
|
6
|
+
module Sms
|
7
|
+
module AuthorizationsControllerOverride
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
def new
|
12
|
+
enforce_permission_to :create, :authorization, authorization: authorization
|
13
|
+
|
14
|
+
flash.now[:error] = I18n.t("decidim.action_delegator.authorizations.new.missing_phone_error") unless direct_authorization && membership_phone
|
15
|
+
|
16
|
+
@form = Decidim::Verifications::Sms::MobilePhoneForm.new mobile_phone_number: membership_phone
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def direct_authorization
|
22
|
+
@direct_authorization ||= Decidim::Authorization.find_by(
|
23
|
+
user: current_user,
|
24
|
+
name: "direct_verifications"
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def membership_phone
|
29
|
+
return nil unless direct_authorization
|
30
|
+
|
31
|
+
direct_authorization.metadata["membership_phone"]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
module Admin
|
6
|
+
# A form object used to create a Delegation
|
7
|
+
#
|
8
|
+
class DelegationForm < Form
|
9
|
+
attribute :granter_id, Integer
|
10
|
+
attribute :grantee_id, Integer
|
11
|
+
|
12
|
+
validates :granter_id, presence: true
|
13
|
+
validates :grantee_id, presence: true
|
14
|
+
|
15
|
+
def granter
|
16
|
+
User.find_by(id: granter_id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def grantee
|
20
|
+
User.find_by(id: grantee_id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
module Consultations
|
6
|
+
module VoteFormOverride
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
attribute :decidim_consultations_delegation_id, Integer
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
module Admin
|
6
|
+
module DelegationHelper
|
7
|
+
def granters_for_select
|
8
|
+
current_organization.users
|
9
|
+
end
|
10
|
+
|
11
|
+
def grantees_for_select
|
12
|
+
current_organization.users
|
13
|
+
end
|
14
|
+
|
15
|
+
def consultations_for_select
|
16
|
+
organization_consultations.map do |consultation|
|
17
|
+
ConsultationPresenter.new(consultation)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def organization_consultations
|
22
|
+
Decidim::Consultations::OrganizationConsultations.new(current_organization).query
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
class ExportConsultationResultsJob < ApplicationJob
|
6
|
+
queue_as :default
|
7
|
+
|
8
|
+
def perform(user, consultation, results_type)
|
9
|
+
@consultation = consultation
|
10
|
+
@results_type = results_type.to_sym
|
11
|
+
|
12
|
+
export_data = Decidim::Exporters
|
13
|
+
.find_exporter("CSV")
|
14
|
+
.new(collection, serializer)
|
15
|
+
.export
|
16
|
+
|
17
|
+
Decidim::ExportMailer.export(user, filename, export_data).deliver_now
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :consultation, :results_type
|
23
|
+
|
24
|
+
def collection
|
25
|
+
query_class.new(consultation).query
|
26
|
+
end
|
27
|
+
|
28
|
+
def query_class
|
29
|
+
case results_type
|
30
|
+
when :sum_of_weights
|
31
|
+
SumOfWeights
|
32
|
+
when :type_and_weight
|
33
|
+
TypeAndWeight
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def serializer
|
38
|
+
case results_type
|
39
|
+
when :sum_of_weights
|
40
|
+
SumOfWeightsSerializer
|
41
|
+
when :type_and_weight
|
42
|
+
ConsultationResultsSerializer
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def filename
|
47
|
+
I18n.t("decidim.admin.consultations.results.export_filename")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "savon"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module ActionDelegator
|
7
|
+
class SendSmsJobException < StandardError; end
|
8
|
+
class SendSmsJob < ApplicationJob
|
9
|
+
queue_as :default
|
10
|
+
|
11
|
+
SMSVIRTUAL_WSDL_URL = "https://websms.masmovil.com/api_php/smsvirtual.wsdl"
|
12
|
+
|
13
|
+
def perform(sender, mobile_phone_number, message)
|
14
|
+
@sender = sender
|
15
|
+
@mobile_phone_number = mobile_phone_number
|
16
|
+
@message = message
|
17
|
+
|
18
|
+
send_sms!
|
19
|
+
|
20
|
+
raise SendSmsJobException, response unless success?
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :sender, :mobile_phone_number, :message, :response
|
26
|
+
|
27
|
+
def send_sms!
|
28
|
+
@response = client.call(:send_sms,
|
29
|
+
message: {
|
30
|
+
user: ENV["SMS_USER"],
|
31
|
+
pass: ENV["SMS_PASS"],
|
32
|
+
src: sender,
|
33
|
+
dst: mobile_phone_number,
|
34
|
+
msg: message
|
35
|
+
})
|
36
|
+
end
|
37
|
+
|
38
|
+
def success?
|
39
|
+
parsed_response[:code] == "200"
|
40
|
+
end
|
41
|
+
|
42
|
+
def client
|
43
|
+
@client ||= ::Savon.client(wsdl: SMSVIRTUAL_WSDL_URL)
|
44
|
+
end
|
45
|
+
|
46
|
+
def parsed_response
|
47
|
+
return @parsed_response if @parsed_response
|
48
|
+
|
49
|
+
doc = Nokogiri::XML response.body[:send_sms_response][:result]
|
50
|
+
|
51
|
+
@parsed_response = {
|
52
|
+
code: doc.xpath("//codigo").text,
|
53
|
+
description: doc.xpath("//descripcion").text
|
54
|
+
}
|
55
|
+
|
56
|
+
@parsed_response
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "twilio-ruby"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module ActionDelegator
|
7
|
+
class TwilioSendSmsJob < ApplicationJob
|
8
|
+
queue_as :default
|
9
|
+
|
10
|
+
def perform(sender, mobile_phone_number, message)
|
11
|
+
@sender = sender
|
12
|
+
@mobile_phone_number = mobile_phone_number
|
13
|
+
@message = message
|
14
|
+
|
15
|
+
send_sms!
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :sender, :mobile_phone_number, :message
|
21
|
+
|
22
|
+
def send_sms!
|
23
|
+
client.messages.create(
|
24
|
+
from: sender,
|
25
|
+
to: mobile_phone_number,
|
26
|
+
body: message
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def client
|
31
|
+
::Twilio::REST::Client.new twilio_account_sid, twilio_auth_token
|
32
|
+
end
|
33
|
+
|
34
|
+
def twilio_account_sid
|
35
|
+
ENV["TWILIO_ACCOUNT_SID"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def twilio_auth_token
|
39
|
+
ENV["TWILIO_AUTH_TOKEN"]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
class Delegation < ApplicationRecord
|
6
|
+
self.table_name = "decidim_action_delegator_delegations"
|
7
|
+
|
8
|
+
belongs_to :granter, class_name: "Decidim::User"
|
9
|
+
belongs_to :grantee, class_name: "Decidim::User"
|
10
|
+
belongs_to :setting,
|
11
|
+
foreign_key: "decidim_action_delegator_setting_id",
|
12
|
+
class_name: "Decidim::ActionDelegator::Setting"
|
13
|
+
|
14
|
+
validates :granter, uniqueness: {
|
15
|
+
scope: [:setting],
|
16
|
+
message: I18n.t("delegations.create.error_granter_unique", scope: "decidim.action_delegator.admin")
|
17
|
+
}
|
18
|
+
|
19
|
+
delegate :consultation, to: :setting
|
20
|
+
|
21
|
+
def self.granted_to?(user, consultation)
|
22
|
+
GranteeDelegations.for(consultation, user).exists?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
# Contains the delegation settings of a consultation. Rather than a single attribute here
|
6
|
+
# a setting is the record itself: a bunch of configuration values.
|
7
|
+
class Setting < ApplicationRecord
|
8
|
+
self.table_name = "decidim_action_delegator_settings"
|
9
|
+
|
10
|
+
belongs_to :consultation,
|
11
|
+
foreign_key: "decidim_consultation_id",
|
12
|
+
class_name: "Decidim::Consultation"
|
13
|
+
has_many :delegations,
|
14
|
+
inverse_of: :setting,
|
15
|
+
foreign_key: "decidim_action_delegator_setting_id",
|
16
|
+
dependent: :destroy
|
17
|
+
|
18
|
+
validates :max_grants, presence: true
|
19
|
+
validates :max_grants, numericality: { greater_than: 0 }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
class UnversionedVote < SimpleDelegator
|
6
|
+
def save
|
7
|
+
PaperTrail.request(enabled: false) do
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def save!
|
13
|
+
PaperTrail.request(enabled: false) do
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
class WhodunnitVote < DelegateClass(Decidim::Consultations::Vote)
|
6
|
+
def initialize(vote, user)
|
7
|
+
@user = user
|
8
|
+
super(vote)
|
9
|
+
end
|
10
|
+
|
11
|
+
def save
|
12
|
+
PaperTrail.request(whodunnit: user.id) do
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def save!
|
18
|
+
PaperTrail.request(whodunnit: user.id) do
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :user
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ActionDelegator
|
5
|
+
module ConsultationsPermissionsExtension
|
6
|
+
# Overrides Decidim::Consultations::Permissions to account for delegation votes
|
7
|
+
def allowed_public_action?
|
8
|
+
return unless permission_action.scope == :public
|
9
|
+
return unless permission_action.subject == :question
|
10
|
+
|
11
|
+
# check if question has been limited by admins first
|
12
|
+
return unless authorized? :vote
|
13
|
+
|
14
|
+
case permission_action.action
|
15
|
+
when :vote
|
16
|
+
toggle_allow(question.can_be_voted_by?(user) || can_be_delegated?(user))
|
17
|
+
when :unvote
|
18
|
+
toggle_allow(question.can_be_unvoted_by?(user))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def can_be_delegated?(user)
|
23
|
+
Delegation.granted_to?(user, question.consultation)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|