decidim-core 0.12.2 → 0.13.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/decidim/modules/_order-by.scss +4 -1
- data/app/cells/decidim/author/comments.erb +2 -2
- data/app/cells/decidim/author/date.erb +1 -1
- data/app/cells/decidim/author_cell.rb +22 -38
- data/app/cells/decidim/card_m/authors.erb +9 -0
- data/app/cells/decidim/card_m/status.erb +1 -1
- data/app/cells/decidim/card_m_cell.rb +8 -0
- data/app/cells/decidim/collapsible_authors/show.erb +16 -0
- data/app/cells/decidim/collapsible_authors_cell.rb +32 -0
- data/app/cells/decidim/invitations_toggle/content.erb +1 -0
- data/app/cells/decidim/invitations_toggle/label.erb +1 -0
- data/app/cells/decidim/invitations_toggle_cell.rb +27 -0
- data/app/cells/decidim/toggle/show.erb +8 -0
- data/app/cells/decidim/toggle_cell.rb +42 -0
- data/app/cells/decidim/tos_page/refuse_btn_modal.erb +25 -14
- data/app/commands/decidim/create_omniauth_registration.rb +1 -1
- data/app/commands/decidim/create_registration.rb +1 -1
- data/app/commands/decidim/create_report.rb +10 -10
- data/app/commands/decidim/invite_friends.rb +48 -0
- data/app/commands/decidim/invite_user.rb +4 -2
- data/app/commands/decidim/unsubscribe_settings.rb +3 -3
- data/app/commands/decidim/update_notifications_settings.rb +1 -1
- data/app/controllers/concerns/decidim/needs_tos_accepted.rb +6 -1
- data/app/controllers/decidim/data_portability_controller.rb +55 -0
- data/app/controllers/decidim/devise/invitations_controller.rb +1 -0
- data/app/controllers/decidim/invitations_controller.rb +32 -0
- data/app/controllers/decidim/newsletters_opt_in_controller.rb +31 -0
- data/app/forms/decidim/account_form.rb +1 -1
- data/app/forms/decidim/invitations_form.rb +37 -0
- data/app/forms/decidim/notifications_settings_form.rb +5 -0
- data/app/forms/decidim/omniauth_registration_form.rb +1 -1
- data/app/forms/decidim/registration_form.rb +7 -1
- data/app/helpers/decidim/cells_helper.rb +44 -0
- data/app/jobs/decidim/data_portability_export_job.rb +21 -0
- data/app/jobs/decidim/newsletters_opt_in_job.rb +11 -0
- data/app/mailers/decidim/export_mailer.rb +13 -0
- data/app/mailers/decidim/newsletters_opt_in_mailer.rb +15 -0
- data/app/models/decidim/coauthorship.rb +23 -0
- data/app/models/decidim/follow.rb +10 -0
- data/app/models/decidim/identity.rb +10 -0
- data/app/models/decidim/messaging/conversation.rb +10 -0
- data/app/models/decidim/notification.rb +10 -0
- data/app/models/decidim/participatory_space_private_user.rb +10 -0
- data/app/models/decidim/report.rb +10 -0
- data/app/models/decidim/user.rb +16 -1
- data/app/models/decidim/user_group.rb +9 -0
- data/app/services/decidim/action_authorizer.rb +1 -1
- data/app/uploaders/decidim/avatar_uploader.rb +6 -2
- data/app/uploaders/decidim/data_portability_uploader.rb +19 -0
- data/app/views/decidim/data_portability/export.html.erb +1 -0
- data/app/views/decidim/data_portability/show.html.erb +5 -0
- data/app/views/decidim/devise/invitations/edit.html.erb +1 -1
- data/app/views/decidim/devise/shared/_newsletter_modal.html.erb +13 -13
- data/app/views/decidim/export_mailer/data_portability_export.html.erb +2 -0
- data/app/views/decidim/invitations/index.html.erb +48 -0
- data/app/views/decidim/newsletters_opt_in_mailer/notify.html.erb +23 -0
- data/app/views/decidim/profiles/_user.html.erb +1 -1
- data/app/views/devise/mailer/invite_friend.html.erb +27 -0
- data/app/views/devise/mailer/invite_friend.text.erb +19 -0
- data/app/views/layouts/decidim/_user_menu.html.erb +1 -0
- data/config/locales/ca.yml +68 -2
- data/config/locales/en.yml +73 -3
- data/config/locales/es-PY.yml +67 -1
- data/config/locales/es.yml +67 -1
- data/config/locales/eu.yml +68 -2
- data/config/locales/fi.yml +69 -3
- data/config/locales/fr.yml +136 -70
- data/config/locales/gl.yml +69 -3
- data/config/locales/it.yml +69 -3
- data/config/locales/nl.yml +69 -3
- data/config/locales/pl.yml +69 -3
- data/config/locales/pt-BR.yml +69 -3
- data/config/locales/pt.yml +69 -3
- data/config/locales/ru.yml +45 -2
- data/config/locales/sv.yml +69 -3
- data/config/locales/uk.yml +61 -2
- data/config/routes.rb +10 -0
- data/db/migrate/20171212103803_create_unique_nicknames.rb +1 -1
- data/db/migrate/20180221101934_fix_nickname_index.rb +3 -1
- data/db/migrate/20180427141253_create_coauthorships.rb +13 -0
- data/db/migrate/20180611121852_change_newsletter_notification_type_value.rb +21 -0
- data/lib/decidim/api/authorable_interface.rb +10 -1
- data/lib/decidim/authorable.rb +4 -1
- data/lib/decidim/coauthorable.rb +69 -0
- data/lib/decidim/component_manifest.rb +4 -0
- data/lib/decidim/core.rb +10 -0
- data/lib/decidim/core/engine.rb +5 -0
- data/lib/decidim/core/test.rb +1 -0
- data/lib/decidim/core/test/factories.rb +9 -1
- data/lib/decidim/core/test/shared_examples/coauthorable.rb +111 -0
- data/lib/decidim/core/test/shared_examples/coauthorable_interface_examples.rb +31 -0
- data/lib/decidim/core/test/shared_examples/simple_event.rb +7 -1
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/data_portability.rb +29 -0
- data/lib/decidim/data_portability_file_reader.rb +56 -0
- data/lib/decidim/data_portability_file_zipper.rb +55 -0
- data/lib/decidim/data_portability_serializers.rb +23 -0
- data/lib/decidim/data_portability_serializers/data_portability_conversation_serializer.rb +42 -0
- data/lib/decidim/data_portability_serializers/data_portability_follow_serializer.rb +23 -0
- data/lib/decidim/data_portability_serializers/data_portability_identity_serializer.rb +25 -0
- data/lib/decidim/data_portability_serializers/data_portability_notification_serializer.rb +26 -0
- data/lib/decidim/data_portability_serializers/data_portability_participatory_space_private_user_serializer.rb +25 -0
- data/lib/decidim/data_portability_serializers/data_portability_report_serializer.rb +36 -0
- data/lib/decidim/data_portability_serializers/data_portability_user_group_serializer.rb +21 -0
- data/lib/decidim/data_portability_serializers/data_portability_user_serializer.rb +55 -0
- data/lib/decidim/events.rb +1 -0
- data/lib/decidim/events/coauthor_event.rb +42 -0
- data/lib/decidim/exporters/csv.rb +0 -1
- data/lib/decidim/form_builder.rb +1 -2
- data/lib/decidim/nicknamizable.rb +15 -4
- data/lib/decidim/participable.rb +7 -0
- data/lib/decidim/participatory_space_manifest.rb +4 -0
- data/lib/devise/models/decidim_newsletterable.rb +60 -0
- data/lib/tasks/decidim_tasks.rake +29 -0
- metadata +73 -28
@@ -43,14 +43,16 @@ module Decidim
|
|
43
43
|
@user = Decidim::User.new(
|
44
44
|
name: form.name,
|
45
45
|
email: form.email.downcase,
|
46
|
-
nickname: User.nicknamize(form.name),
|
46
|
+
nickname: User.nicknamize(form.name, organization: form.organization),
|
47
47
|
organization: form.organization,
|
48
48
|
admin: form.role == "admin",
|
49
49
|
roles: form.role == "admin" ? [] : [form.role].compact
|
50
50
|
)
|
51
51
|
@user.invite!(
|
52
52
|
form.invited_by,
|
53
|
-
|
53
|
+
{
|
54
|
+
invitation_instructions: form.invitation_instructions
|
55
|
+
}.merge(form.try(:extra_email_options) || {})
|
54
56
|
)
|
55
57
|
end
|
56
58
|
end
|
@@ -6,13 +6,13 @@ module Decidim
|
|
6
6
|
# unsubscribe user from newsletter.
|
7
7
|
#
|
8
8
|
# user - The user to be updated.
|
9
|
-
#
|
9
|
+
# newsletter_notifications_at - to be nil
|
10
10
|
def initialize(user)
|
11
11
|
@user = user
|
12
12
|
end
|
13
13
|
|
14
14
|
def call
|
15
|
-
return broadcast(:invalid) unless @user.
|
15
|
+
return broadcast(:invalid) unless @user.newsletter_notifications_at?
|
16
16
|
|
17
17
|
update_settings
|
18
18
|
@user.save!
|
@@ -23,7 +23,7 @@ module Decidim
|
|
23
23
|
private
|
24
24
|
|
25
25
|
def update_settings
|
26
|
-
@user.
|
26
|
+
@user.newsletter_notifications_at = nil
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -25,7 +25,7 @@ module Decidim
|
|
25
25
|
|
26
26
|
def update_notifications_settings
|
27
27
|
@user.email_on_notification = @form.email_on_notification
|
28
|
-
@user.
|
28
|
+
@user.newsletter_notifications_at = @form.newsletter_notifications_at
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -25,7 +25,12 @@ module Decidim
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def permitted_paths?
|
28
|
-
permitted_paths = [tos_path,
|
28
|
+
permitted_paths = [tos_path,
|
29
|
+
decidim.delete_account_path,
|
30
|
+
decidim.accept_tos_path,
|
31
|
+
decidim.data_portability_path,
|
32
|
+
decidim.export_data_portability_path,
|
33
|
+
decidim.download_file_data_portability_path]
|
29
34
|
permitted_paths.include?(request.path)
|
30
35
|
end
|
31
36
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zip"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
# The controller to handle the user's download_my_data page.
|
7
|
+
class DataPortabilityController < Decidim::ApplicationController
|
8
|
+
include Decidim::UserProfile
|
9
|
+
|
10
|
+
def show
|
11
|
+
enforce_permission_to :show, :user, current_user: current_user
|
12
|
+
|
13
|
+
@account = form(AccountForm).from_model(current_user)
|
14
|
+
end
|
15
|
+
|
16
|
+
def export
|
17
|
+
enforce_permission_to :export, :user, current_user: current_user
|
18
|
+
|
19
|
+
DataPortabilityExportJob.perform_later(current_user, export_format)
|
20
|
+
|
21
|
+
flash[:notice] = t("decidim.account.data_portability_export.notice")
|
22
|
+
|
23
|
+
redirect_back(fallback_location: data_portability_path)
|
24
|
+
end
|
25
|
+
|
26
|
+
def download_file
|
27
|
+
enforce_permission_to :download, :user, current_user: current_user
|
28
|
+
|
29
|
+
if params[:token].present?
|
30
|
+
file_reader = Decidim::DataPortabilityFileReader.new(current_user, params[:token])
|
31
|
+
if file_reader.valid_token?
|
32
|
+
file = File.open(file_reader.file_path)
|
33
|
+
if File.exist?(file)
|
34
|
+
send_file file, type: "application/zip", disposition: "attachment"
|
35
|
+
else
|
36
|
+
flash[:error] = t("decidim.account.data_portability_export.file_no_exists")
|
37
|
+
redirect_to data_portability_path
|
38
|
+
end
|
39
|
+
else
|
40
|
+
flash[:error] = t("decidim.account.data_portability_export.invalid_token")
|
41
|
+
redirect_to data_portability_path
|
42
|
+
end
|
43
|
+
else
|
44
|
+
flash[:error] = t("decidim.account.data_portability_export.no_token")
|
45
|
+
redirect_to data_portability_path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def export_format
|
52
|
+
"CSV"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -25,6 +25,7 @@ module Decidim
|
|
25
25
|
# When a managed user accepts the invitation is promoted to non-managed user.
|
26
26
|
def accept_resource
|
27
27
|
resource = resource_class.accept_invitation!(update_resource_params)
|
28
|
+
resource.update!(newsletter_notifications_at: Time.zone.now) if update_resource_params[:newsletter_notifications]
|
28
29
|
resource.update!(managed: false) if resource.managed?
|
29
30
|
resource.update!(accepted_tos_version: resource.organization.tos_version)
|
30
31
|
resource
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
# The controller to handle friends invitations by the current user.
|
5
|
+
class InvitationsController < Decidim::ApplicationController
|
6
|
+
include FormFactory
|
7
|
+
|
8
|
+
def index
|
9
|
+
@form = form(InvitationsForm).instance
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
@form = form(InvitationsForm).from_params(params)
|
14
|
+
|
15
|
+
InviteFriends.call(@form) do
|
16
|
+
on(:ok) do
|
17
|
+
flash[:notice] = t("invitations.create.success", scope: "decidim")
|
18
|
+
redirect_to account_path
|
19
|
+
end
|
20
|
+
|
21
|
+
on(:invalid) do
|
22
|
+
flash.now[:alert] = if @form.emails.empty?
|
23
|
+
t("invitations.create.error_empty_form", scope: "decidim")
|
24
|
+
else
|
25
|
+
t("invitations.create.error", scope: "decidim")
|
26
|
+
end
|
27
|
+
render action: :index
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
# The controller to control newsletter Opt-in for GDPR
|
5
|
+
class NewslettersOptInController < Decidim::ApplicationController
|
6
|
+
include FormFactory
|
7
|
+
|
8
|
+
before_action :check_current_user_with_token
|
9
|
+
|
10
|
+
def update
|
11
|
+
enforce_permission_to :update, :user, current_user: current_user
|
12
|
+
|
13
|
+
current_user.newsletter_opt_in_validate
|
14
|
+
if current_user.save
|
15
|
+
flash[:notice] = t(".success")
|
16
|
+
else
|
17
|
+
flash[:alert] = t(".error")
|
18
|
+
end
|
19
|
+
redirect_to decidim.root_path(host: current_organization)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def check_current_user_with_token
|
25
|
+
unless current_user.newsletter_token == params[:token]
|
26
|
+
flash[:alert] = t("newsletters_opt_in.unathorized", scope: "decidim")
|
27
|
+
redirect_to decidim.root_path(host: current_organization)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -22,7 +22,7 @@ module Decidim
|
|
22
22
|
|
23
23
|
validates :nickname, length: { maximum: Decidim::User.nickname_max_length, allow_blank: true }
|
24
24
|
validates :password, confirmation: true
|
25
|
-
validates :password,
|
25
|
+
validates :password, password: { name: :name, email: :email, username: :nickname }, if: -> { password.present? }
|
26
26
|
validates :password_confirmation, presence: true, if: :password_present
|
27
27
|
validates :avatar, file_size: { less_than_or_equal_to: ->(_record) { Decidim.maximum_avatar_size } }
|
28
28
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
# This form holds the data for the invitations system.
|
5
|
+
class InvitationsForm < Form
|
6
|
+
mimic :invitations
|
7
|
+
|
8
|
+
attribute :email_1, String
|
9
|
+
attribute :email_2, String
|
10
|
+
attribute :email_3, String
|
11
|
+
attribute :email_4, String
|
12
|
+
attribute :email_5, String
|
13
|
+
attribute :email_6, String
|
14
|
+
attribute :custom_text, String
|
15
|
+
|
16
|
+
validates :email_1,
|
17
|
+
:email_2,
|
18
|
+
:email_3,
|
19
|
+
:email_4,
|
20
|
+
:email_5,
|
21
|
+
:email_6,
|
22
|
+
"valid_email_2/email": true,
|
23
|
+
allow_blank: true
|
24
|
+
validates :emails, presence: true
|
25
|
+
|
26
|
+
def emails
|
27
|
+
[email_1, email_2, email_3, email_4, email_5, email_6].uniq.select(&:present?)
|
28
|
+
end
|
29
|
+
|
30
|
+
def clean_emails
|
31
|
+
existing_emails = Decidim::User
|
32
|
+
.where(organization: current_organization, email: emails)
|
33
|
+
.pluck(:email)
|
34
|
+
emails - existing_emails
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -22,7 +22,8 @@ module Decidim
|
|
22
22
|
validates :name, presence: true
|
23
23
|
validates :nickname, presence: true, length: { maximum: Decidim::User.nickname_max_length }
|
24
24
|
validates :email, presence: true, 'valid_email_2/email': { disposable: true }
|
25
|
-
validates :password,
|
25
|
+
validates :password, confirmation: true
|
26
|
+
validates :password, password: { name: :name, email: :email, username: :nickname }
|
26
27
|
validates :password_confirmation, presence: true
|
27
28
|
validates :tos_agreement, allow_nil: false, acceptance: true
|
28
29
|
|
@@ -39,6 +40,11 @@ module Decidim
|
|
39
40
|
sign_up_as == "user_group"
|
40
41
|
end
|
41
42
|
|
43
|
+
def newsletter_at
|
44
|
+
return nil unless newsletter?
|
45
|
+
Time.zone.now
|
46
|
+
end
|
47
|
+
|
42
48
|
private
|
43
49
|
|
44
50
|
def email_unique_in_organization
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module CellsHelper
|
5
|
+
def from_context
|
6
|
+
options[:from].presence || context[:from].presence
|
7
|
+
end
|
8
|
+
|
9
|
+
def proposals_controller?
|
10
|
+
context[:controller].class.to_s == "Decidim::Proposals::ProposalsController"
|
11
|
+
end
|
12
|
+
|
13
|
+
def posts_controller?
|
14
|
+
context[:controller].class.to_s == "Decidim::Blogs::PostsController"
|
15
|
+
end
|
16
|
+
|
17
|
+
def index_action?
|
18
|
+
context[:controller].action_name == "index"
|
19
|
+
end
|
20
|
+
|
21
|
+
def show_action?
|
22
|
+
context[:controller].action_name == "show"
|
23
|
+
end
|
24
|
+
|
25
|
+
def current_component
|
26
|
+
from_context.component
|
27
|
+
end
|
28
|
+
|
29
|
+
def withdrawable?
|
30
|
+
return unless from_context
|
31
|
+
return unless proposals_controller?
|
32
|
+
return if index_action?
|
33
|
+
from_context.withdrawable_by?(current_user)
|
34
|
+
end
|
35
|
+
|
36
|
+
def flagable?
|
37
|
+
return unless from_context
|
38
|
+
return unless proposals_controller?
|
39
|
+
return if index_action?
|
40
|
+
return if from_context.official?
|
41
|
+
true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
class DataPortabilityExportJob < ApplicationJob
|
5
|
+
queue_as :default
|
6
|
+
|
7
|
+
def perform(user, format)
|
8
|
+
objects = Decidim::DataPortabilitySerializers.data_entities
|
9
|
+
export_data = []
|
10
|
+
export_images = []
|
11
|
+
|
12
|
+
objects.each do |object|
|
13
|
+
klass = Object.const_get(object)
|
14
|
+
export_data << [klass.model_name.name.parameterize.pluralize, Decidim::Exporters.find_exporter(format).new(klass.user_collection(user), klass.export_serializer).export]
|
15
|
+
export_images << [klass.model_name.name.parameterize.pluralize, klass.data_portability_images(user).flatten] unless klass.data_portability_images(user).nil?
|
16
|
+
end
|
17
|
+
|
18
|
+
ExportMailer.data_portability_export(user, export_data, export_images).deliver_now
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -25,5 +25,18 @@ module Decidim
|
|
25
25
|
mail(to: "#{user.name} <#{user.email}>", subject: I18n.t("decidim.export_mailer.subject", name: filename))
|
26
26
|
end
|
27
27
|
end
|
28
|
+
|
29
|
+
def data_portability_export(user, export_data, export_images)
|
30
|
+
@user = user
|
31
|
+
@organization = user.organization
|
32
|
+
|
33
|
+
file_zipper = Decidim::DataPortabilityFileZipper.new(@user, export_data, export_images)
|
34
|
+
file_zipper.make_zip
|
35
|
+
|
36
|
+
with_user(user) do
|
37
|
+
@token = file_zipper.token
|
38
|
+
mail(to: "#{user.name} <#{user.email}>", subject: I18n.t("decidim.export_mailer.subject", name: user.name))
|
39
|
+
end
|
40
|
+
end
|
28
41
|
end
|
29
42
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
# A custom mailer for Decidim so we can notify users to verify
|
5
|
+
# his own newsletter notifications settings. GDPR releated
|
6
|
+
class NewslettersOptInMailer < ApplicationMailer
|
7
|
+
def notify(user, token)
|
8
|
+
@user = user
|
9
|
+
@organization = user.organization
|
10
|
+
@token = token
|
11
|
+
|
12
|
+
mail(to: user.email, subject: I18n.t("decidim.newsletters_opt_in_mailer.notify.subject", organization_name: @organization.name))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
class Coauthorship < ApplicationRecord
|
5
|
+
include Decidim::Authorable
|
6
|
+
|
7
|
+
belongs_to :coauthorable, polymorphic: true, counter_cache: true
|
8
|
+
|
9
|
+
validates :coauthorable, presence: true
|
10
|
+
|
11
|
+
def identity
|
12
|
+
user_group || author
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# As it is used to validate by comparing to author.organization
|
18
|
+
# @returns The Organization for the Coauthorable
|
19
|
+
def organization
|
20
|
+
coauthorable&.organization
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -2,9 +2,19 @@
|
|
2
2
|
|
3
3
|
module Decidim
|
4
4
|
class Follow < ApplicationRecord
|
5
|
+
include Decidim::DataPortability
|
6
|
+
|
5
7
|
belongs_to :followable, foreign_key: "decidim_followable_id", foreign_type: "decidim_followable_type", polymorphic: true
|
6
8
|
belongs_to :user, foreign_key: "decidim_user_id", class_name: "Decidim::User"
|
7
9
|
|
8
10
|
validates :user, uniqueness: { scope: [:followable] }
|
11
|
+
|
12
|
+
def self.user_collection(user)
|
13
|
+
where(decidim_user_id: user.id)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.export_serializer
|
17
|
+
Decidim::DataPortabilitySerializers::DataPortabilityFollowSerializer
|
18
|
+
end
|
9
19
|
end
|
10
20
|
end
|