decidim-spam_detection 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a68cdcfc4bee9d6fe8d391eb22a121b2f7cfb2a47557c1081b4ae47e649fc7f
4
- data.tar.gz: b7ee10f5d795d9044c7bd0d6270d899f3ce90e72496221739dad6715cd287de8
3
+ metadata.gz: 38cc3310b2ed4c7e48cadea2c1bf9f0ff86d8f28bad7b3e04398d5922598442d
4
+ data.tar.gz: be191b16b6827c2e6963b72578fe899d1feace76156b87cb246928dc869619d3
5
5
  SHA512:
6
- metadata.gz: 921412beab2eb7bbf993bb1f6f02f95556ebdd7bb61ac18695764176762a870e48ac572a9f86b0cc4dcdc91a2ed09a6786d3e54b7f8b14f4b56e912992c8a9ba
7
- data.tar.gz: d46133286084b2a2c353a8fb50a0fc0460f299925e8335c791f6f2472d66c9cf2ea70ef647f616645105584630f798573ef988ae4c862c1d3a2dc713e87b4d8d
6
+ metadata.gz: ef0c0fcc58dfdb427725cc53ad5a3fa2829b0482180e4b311427a483345b97f09ec90d55ffdcfaf778903ed00913bf17976ae56e2a9fb13deb17605cf45c0425
7
+ data.tar.gz: 9d6b782f0b236cd000b1bf361b5d83524c037da23fa22aa779321f5c09fafbc849d45d713c965b2e9a6eb2a37d465565e91b33bfcff0a1e73436065ee76265b6
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module SpamDetection
5
+ class NotifyAdmins < ApplicationJob
6
+ queue_as :default
7
+
8
+ def perform(results_hash)
9
+ results_hash.each do |id, result|
10
+ next if result.keys == [:nothing]
11
+
12
+ Decidim::Organization.find(id).admins.each do |admin|
13
+ Decidim::SpamDetection::SpamDetectionMailer.notify_detection(admin, result).deliver_later
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module SpamDetection
5
+ class SpamDetectionMailer < Decidim::ApplicationMailer
6
+ def notify_detection(user, results)
7
+ with_user(user) do
8
+ @reported_count = results[:reported_user]
9
+ @blocked_count = results[:blocked_user]
10
+ @organization = user.organization
11
+ @user = user
12
+
13
+ subject = I18n.t("notify_detection.subject", scope: "decidim.spam_detection_mailer")
14
+ mail(to: @user.email, subject: subject)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -27,7 +27,7 @@ module Decidim
27
27
  .where(admin: false, blocked: false, deleted_at: nil)
28
28
  .where("(extended_data #> '{spam_detection, unreported_at}') is null")
29
29
  .where("(extended_data #> '{spam_detection, unblocked_at}') is null")
30
- @results = []
30
+ @results = {}
31
31
  end
32
32
 
33
33
  def self.call
@@ -38,11 +38,15 @@ module Decidim
38
38
  spam_probability_array = Decidim::SpamDetection::ApiProxy.request(cleaned_users)
39
39
 
40
40
  mark_spam_users(merge_response_with_users(spam_probability_array))
41
+ notify_admins!
41
42
  end
42
43
 
43
44
  def mark_spam_users(probability_array)
44
45
  probability_array.each do |probability_hash|
45
- @results << Decidim::SpamDetection::SpamUserCommandAdapter.call(probability_hash).result
46
+ result = Decidim::SpamDetection::SpamUserCommandAdapter.call(probability_hash).result
47
+ organization_id = probability_hash["decidim_organization_id"]
48
+
49
+ add_to_results(organization_id.to_s, result)
46
50
  end
47
51
  end
48
52
 
@@ -56,7 +60,23 @@ module Decidim
56
60
  end
57
61
 
58
62
  def status
59
- @results.tally
63
+ @results.each_with_object({}) do |result, hash|
64
+ hash[result[0]] = result[1].tally
65
+ end
66
+ end
67
+
68
+ def notify_admins!
69
+ Decidim::SpamDetection::NotifyAdmins.perform_later(status)
70
+ end
71
+
72
+ private
73
+
74
+ def add_to_results(organization_id, result)
75
+ if @results[organization_id]
76
+ @results[organization_id] << result
77
+ else
78
+ @results[organization_id] = [result]
79
+ end
60
80
  end
61
81
  end
62
82
  end
@@ -0,0 +1,14 @@
1
+ <p class="email-greeting"><%= t(".hello", name: @user.name) %></p>
2
+ <p><%= t(".intro") %></p>
3
+
4
+ <% if @reported_count.present? %>
5
+ <p>
6
+ <%= t(".reported_count", count: @reported_count) %>
7
+ </p>
8
+ <% end %>
9
+
10
+ <% if @blocked_count.present? %>
11
+ <p>
12
+ <%= t(".blocked_count", count: @blocked_count) %>
13
+ </p>
14
+ <% end %>
@@ -1,7 +1,7 @@
1
1
  ---
2
2
 
3
3
  base_locale: en
4
- locales: [en]
4
+ locales: [en, fr, es, ca]
5
5
 
6
6
  ignore_unused:
7
7
  - "decidim.components.spam_detection.name"
@@ -0,0 +1,16 @@
1
+ ---
2
+ ca:
3
+ decidim:
4
+ components:
5
+ spam_detection:
6
+ name: SpamDetection
7
+ spam_detection:
8
+ spam_detection_mailer:
9
+ notify_detection:
10
+ blocked_count: blocked_count %{count}
11
+ hello: Hello %{name}
12
+ intro: Aquí teniu l'informe de la tasca de detecció de correu brossa
13
+ reported_count: reported_count %{count}
14
+ spam_detection_mailer:
15
+ notify_detection:
16
+ subject: Resum de detecció de correu brossa
@@ -4,3 +4,13 @@ en:
4
4
  components:
5
5
  spam_detection:
6
6
  name: SpamDetection
7
+ spam_detection:
8
+ spam_detection_mailer:
9
+ notify_detection:
10
+ blocked_count: 'Blocked users count: %{count}'
11
+ hello: Hello %{name}
12
+ intro: Here is the report of the spam detection task
13
+ reported_count: 'Reported users count: %{count}'
14
+ spam_detection_mailer:
15
+ notify_detection:
16
+ subject: Spam detection digest
@@ -0,0 +1,16 @@
1
+ ---
2
+ es:
3
+ decidim:
4
+ components:
5
+ spam_detection:
6
+ name: SpamDetection
7
+ spam_detection:
8
+ spam_detection_mailer:
9
+ notify_detection:
10
+ blocked_count: blocked_count %{count}
11
+ hello: Hello %{name}
12
+ intro: Here is the report of the spam detection task
13
+ reported_count: reported_count %{count}
14
+ spam_detection_mailer:
15
+ notify_detection:
16
+ subject: Subject
@@ -0,0 +1,16 @@
1
+ ---
2
+ fr:
3
+ decidim:
4
+ components:
5
+ spam_detection:
6
+ name: SpamDetection
7
+ spam_detection:
8
+ spam_detection_mailer:
9
+ notify_detection:
10
+ blocked_count: blocked_count %{count}
11
+ hello: Hello %{name}
12
+ intro: Here is the report of the spam detection task
13
+ reported_count: reported_count %{count}
14
+ spam_detection_mailer:
15
+ notify_detection:
16
+ subject: Subject
@@ -24,6 +24,14 @@ module Decidim
24
24
  raise NotImplementedError
25
25
  end
26
26
 
27
+ def reason
28
+ raise NotImplementedError
29
+ end
30
+
31
+ def details
32
+ raise NotImplementedError
33
+ end
34
+
27
35
  def moderation_user
28
36
  moderation_admin_params = {
29
37
  name: SPAM_USER[:name],
@@ -56,9 +64,10 @@ module Decidim
56
64
  end
57
65
 
58
66
  def add_spam_detection_metadata!(metadata)
59
- @user.update!(extended_data: @user.extended_data
60
- .dup
61
- .deep_merge("spam_detection" => metadata))
67
+ @user.extended_data = @user.extended_data
68
+ .dup
69
+ .deep_merge("spam_detection" => metadata)
70
+ @user.save(validate: false)
62
71
  end
63
72
  end
64
73
  end
@@ -9,28 +9,60 @@ module Decidim
9
9
  prepend Decidim::SpamDetection::Command
10
10
 
11
11
  def call
12
- form = form(Decidim::Admin::BlockUserForm).from_params(
13
- justification: "The user was blocked because of a high spam probability by Decidim spam detection bot"
14
- )
12
+ ActiveRecord::Base.transaction do
13
+ create_user_moderation
14
+ block!
15
+ register_justification!
16
+ notify_user!
17
+ add_spam_detection_metadata!({ "blocked_at" => Time.current, "spam_probability" => @probability })
18
+ end
15
19
 
16
- moderator = @moderator
17
- user = @user
20
+ Rails.logger.info("User with id #{@user["id"]} was blocked for spam with a probability of #{@probability}%")
18
21
 
19
- form.define_singleton_method(:user) { user }
20
- form.define_singleton_method(:current_user) { moderator }
21
- form.define_singleton_method(:blocking_user) { moderator }
22
-
23
- Decidim::Admin::BlockUser.call(form)
22
+ :ok
23
+ end
24
24
 
25
- add_spam_detection_metadata!({
26
- "blocked_at" => Time.current,
27
- "spam_probability" => @probability
28
- })
25
+ private
29
26
 
27
+ def create_user_moderation
30
28
  @user.create_user_moderation
31
- Rails.logger.info("User with id #{@user["id"]} was blocked for spam")
29
+ end
32
30
 
33
- :ok
31
+ def register_justification!
32
+ UserBlock.create!(justification: reason, user: @user, blocking_user: @moderator)
33
+ end
34
+
35
+ def notify_user!
36
+ Decidim::BlockUserJob.perform_later(@user, reason)
37
+ end
38
+
39
+ def block!
40
+ Decidim.traceability.perform_action!(
41
+ "block",
42
+ @user,
43
+ @moderator,
44
+ extra: {
45
+ reportable_type: @user.class.name,
46
+ current_justification: reason
47
+ },
48
+ resource: {
49
+ # Make sure the action log entry gets the original user name instead
50
+ # of "Blocked user". Otherwise the log entries would show funny
51
+ # messages such as "Mr. Admin blocked user Blocked user"-
52
+ title: @user.name
53
+ }
54
+ ) do
55
+ @user.blocked = true
56
+ @user.blocked_at = Time.current
57
+ @user.blocking = @current_blocking
58
+ @user.extended_data["user_name"] = @user.name
59
+ @user.name = "Blocked user"
60
+ @user.save!
61
+ end
62
+ end
63
+
64
+ def reason
65
+ "The user was blocked because of a high spam probability by Decidim spam detection bot with a probability of #{@probability}%"
34
66
  end
35
67
  end
36
68
  end
@@ -9,29 +9,43 @@ module Decidim
9
9
  prepend Decidim::SpamDetection::Command
10
10
 
11
11
  def call
12
- form = form(Decidim::ReportForm).from_params(
13
- reason: "spam",
14
- details: "The user was marked as spam by Decidim spam detection bot"
15
- )
12
+ ActiveRecord::Base.transaction do
13
+ find_or_create_moderation!
14
+ create_report!
15
+ update_report_count!
16
+ add_spam_detection_metadata!({ "reported_at" => Time.current, "spam_probability" => @probability })
17
+ end
16
18
 
17
- current_organization = @user.organization
18
- moderator = @moderator
19
- user = @user
19
+ Rails.logger.info("User with id #{@user.id} was reported for spam with a probability of #{@probability}%")
20
20
 
21
- report = Decidim::CreateUserReport.new(form, user, moderator)
22
- report.define_singleton_method(:current_organization) { current_organization }
23
- report.define_singleton_method(:current_user) { moderator }
24
- report.define_singleton_method(:reportable) { user }
25
- report.call
21
+ :ok
22
+ end
26
23
 
27
- add_spam_detection_metadata!({
28
- "reported_at" => Time.current,
29
- "spam_probability" => @probability
30
- })
24
+ private
31
25
 
32
- Rails.logger.info("User with id #{user.id} was reported for spam")
26
+ def reason
27
+ "spam"
28
+ end
33
29
 
34
- :ok
30
+ def details
31
+ "The user was marked as spam by Decidim spam detection bot with a probability of #{@probability}%"
32
+ end
33
+
34
+ def find_or_create_moderation!
35
+ @moderation = UserModeration.find_or_create_by!(user: @user)
36
+ end
37
+
38
+ def create_report!
39
+ @report = UserReport.create!(
40
+ moderation: @moderation,
41
+ user: @moderator,
42
+ reason: reason,
43
+ details: details
44
+ )
45
+ end
46
+
47
+ def update_report_count!
48
+ @moderation.update!(report_count: @moderation.report_count + 1)
35
49
  end
36
50
  end
37
51
  end
@@ -5,7 +5,7 @@ module Decidim
5
5
  # This holds the decidim-spam_detection version.
6
6
  module SpamDetection
7
7
  def self.version
8
- "1.0.0"
8
+ "1.1.0"
9
9
  end
10
10
 
11
11
  def self.decidim_version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-spam_detection
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Armand Fardeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-08 00:00:00.000000000 Z
11
+ date: 2022-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: decidim-core
@@ -40,10 +40,15 @@ files:
40
40
  - app/commands/decidim/admin/unblock_user.rb
41
41
  - app/commands/decidim/admin/unreport_user.rb
42
42
  - app/jobs/decidim/spam_detection/mark_users_job.rb
43
+ - app/jobs/decidim/spam_detection/notify_admins.rb
44
+ - app/mailers/decidim/spam_detection/spam_detection_mailer.rb
43
45
  - app/services/decidim/spam_detection/mark_users_service.rb
44
- - config/assets.rb
46
+ - app/views/decidim/spam_detection/spam_detection_mailer/notify_detection.html.erb
45
47
  - config/i18n-tasks.yml
48
+ - config/locales/ca.yml
46
49
  - config/locales/en.yml
50
+ - config/locales/es.yml
51
+ - config/locales/fr.yml
47
52
  - lib/decidim/spam_detection.rb
48
53
  - lib/decidim/spam_detection/abstract_spam_user_command.rb
49
54
  - lib/decidim/spam_detection/admin.rb
data/config/assets.rb DELETED
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- base_path = File.expand_path("..", __dir__)
4
-
5
- Decidim::Webpacker.register_path("#{base_path}/app/packs")
6
- Decidim::Webpacker.register_entrypoints(
7
- decidim_spam_detection: "#{base_path}/app/packs/entrypoints/decidim_spam_detection.js"
8
- )
9
- Decidim::Webpacker.register_stylesheet_import("stylesheets/decidim/spam_detection/spam_detection")