decidim-cdtb 0.1.3 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d908d1cc4021da9869dd10cacb1fe06b360301d4e13f1a70a55fdc90a2712b6a
4
- data.tar.gz: e7a0c808803bbbd6dc75e5bdfaee7b3acfb1311c085f17eb41a9de32fc7795fa
3
+ metadata.gz: 241f6ab9b3dcf2a9c90d13e458459776a5cedf5d0beff5ffbe9114b0c0f687ba
4
+ data.tar.gz: 2d9a4ef96c973b47296869acf12083a4f5862fdab7e7135e6ad36e6674115edc
5
5
  SHA512:
6
- metadata.gz: 20ddde6eddf59ab12b7ca8d6f489692a04183331f0c1ef496b199b4350cdd103d2b23ca94329199d36f2a9e7222ea0c3269da25648ec0acb47bdde6b38666b92
7
- data.tar.gz: 2dd41a8a1f79ffd4506c6b18d58393d3a88d8a021e0acf05cfbd4e4ac1dcc22250294c8de29d7168c2fce29bf2d2df71c0b9905414a3df1e28991aa665be8d36
6
+ metadata.gz: 37c3ba1e514d44cecf61948a84f89b16c01dd67f7993b972fda6f6b006997b0afaabf3dcacf312ff85a9ef142d6f1576dd822824c1d5e492bbc200a4bff3cc20
7
+ data.tar.gz: 1517ff9df9d457abab99ed385d3fb0c7d1e4a6bdf080a8c29ba5fe3a766d8024ae294f37bc8fe4c90142155914bba4bfd20cdf51108a590b33ba168d977cd27e
data/.rubocop.yml CHANGED
@@ -11,7 +11,7 @@ AllCops:
11
11
 
12
12
  Metrics/BlockLength:
13
13
  Enabled: true
14
- Max: 30
14
+ Max: 50
15
15
  Exclude:
16
16
  - lib/tasks/*.rake
17
17
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.1.6] - 2024-04-11 (Malifetes ben fetes)
4
+
5
+ - Add remover users task
6
+
7
+ ## [0.1.5] - 2024-02-08 (Pastissos voladors de colors)
8
+
9
+ - Fix homepage in rubygems.org
10
+ - Add organization id and name in spam csv
11
+
12
+ ## [0.1.4] - 2024-01-30 (Peus grans com gegants)
13
+
14
+ - Add users spam detector task
15
+
3
16
  ## [0.1.3] - 2023-06-23 (Tan iguals com especials)
4
17
 
5
18
  - Validate migrations task
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- decidim-cdtb (0.1.3)
4
+ decidim-cdtb (0.1.6)
5
5
  decidim (>= 0.26.2)
6
6
  rails (>= 6)
7
7
  ruby-progressbar
@@ -775,4 +775,4 @@ DEPENDENCIES
775
775
  sqlite3
776
776
 
777
777
  BUNDLED WITH
778
- 2.3.6
778
+ 2.4.22
data/README.md CHANGED
@@ -36,17 +36,6 @@ bin/rake cdtb:org_by_host_like[vila]
36
36
  host: localhost, time_zone: Madrid, locales: ca + [ca, es, oc], available authorizations: [postal_letter, members_picker_authorization_handler]
37
37
  ```
38
38
 
39
- ### Fix nicknames
40
-
41
- In a previous version than Decidim v0.25 a validation to the `Decidim::User.nickname` was added with a migration to fix existing nicknames. But the migration was only taking into acocunt managed (impersonated) users.
42
-
43
- This task iterates (with `find_each`) over all non managed users and nicknamizes the nickname.
44
-
45
- To execute the task run:
46
-
47
- ```
48
- bin/rake cdtb:fix_nicknames
49
- ```
50
39
 
51
40
  ### Anonymize production dump
52
41
 
@@ -76,6 +65,58 @@ To migrate from S3 to local storage, the identified steps will be:
76
65
  `bin/rake cache:clear`
77
66
  5. Restart the Rails server
78
67
 
68
+ ### Detect spam
69
+
70
+ To detect spam in Decidim.
71
+
72
+ #### Detect spam users
73
+ Detects users susceptible of being spammers. It can run on all organizations or be scoped to a single organization by passing the organization ID as the rake task parameter.
74
+
75
+ This rake task export a .csv with a list of all the searched users. A column indicates if each user is suspicious of being a spammer or not.
76
+ The columns in the CSV are: "ID, "Is suspicious?", "Name", "Email", "Nickname", "Personal URL", "About"
77
+
78
+ Examples:
79
+ `bin/rake cdtb:spam:users[org_id]` --> find users in organization with an id.
80
+ `bin/rake cdtb:spam:users` --> find all users in all organizations.
81
+
82
+ To set custom words in the rake, you can override it with an initalizer:
83
+
84
+ ```
85
+ Decidim::Cdtb.configure do |config|
86
+ config.spam_words = ENV["CDTB_SPAM_WORDS"]&.split(",")
87
+ end
88
+ ```
89
+
90
+ ### Users
91
+
92
+ Tasks related with users.
93
+
94
+ ### Fix nicknames
95
+
96
+ In a previous version than Decidim v0.25 a validation to the `Decidim::User.nickname` was added with a migration to fix existing nicknames. But the migration was only taking into account managed (impersonated) users.
97
+
98
+ This task iterates (with `find_each`) over all non managed users and nicknamizes the nickname.
99
+
100
+ To execute the task run:
101
+
102
+ ```
103
+ bin/rake cdtb:users:fix_nicknames
104
+ ```
105
+
106
+ #### Remove users
107
+
108
+ You can delete users through a CSV with the user ID. The purpose is to be able to eliminate potentially spammy users.
109
+
110
+ This task reports and hide the user's comments, blocks the user, and finally deletes the user.
111
+
112
+ The CSV will have a header and one column with the user ID.
113
+
114
+ To execute the task run:
115
+
116
+ ```
117
+ bundle exec rake cdtb:users:remove[spam_users.csv]
118
+ ```
119
+
79
120
  ### Upgrades:
80
121
 
81
122
  #### Upgrade modules
data/decidim-cdtb.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = "CodiTramuntana's Decidim Toolbelt (cdtb)."
12
12
  spec.description = "A gem to help managing Decidim applications."
13
- spec.homepage = "http://github.com/CodiTramunana/cdtb"
13
+ spec.homepage = "https://github.com/CodiTramuntana/decidim-module-cdtb"
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = ">= 2.7.5"
16
16
 
@@ -10,6 +10,10 @@ module Decidim
10
10
  # Workaround for https://stackoverflow.com/questions/72970170/upgrading-to-rails-6-1-6-1-causes-psychdisallowedclass-tried-to-load-unspecif
11
11
  Rails.application.config.active_record.use_yaml_unsafe_load = true
12
12
  end
13
+
14
+ config.after_initialize do
15
+ Decidim::Cdtb.config.spam_regexp = Regexp.union(Decidim::Cdtb.config.spam_words)
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ module Decidim
6
+ module Cdtb
7
+ module Spam
8
+ # Detect spam behavior in users
9
+ #
10
+ class UserSpamDetector < ::Decidim::Cdtb::Task
11
+ # rubocop:disable Style/RedundantRegexpEscape
12
+ URL_REGEX = %r{(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|
13
+ www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|
14
+ (?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})}.freeze
15
+ # rubocop:enable Style/RedundantRegexpEscape
16
+
17
+ def initialize(organization = nil)
18
+ @organization = organization
19
+ progress_bar = { title: "Decidim::User" }
20
+ super("SPAM DETECTOR", progress_bar: progress_bar)
21
+ end
22
+
23
+ def prepare_execution(_ctx)
24
+ @users = if @organization.present?
25
+ Decidim::User.where(organization: @organization)
26
+ else
27
+ Decidim::User.all
28
+ end
29
+
30
+ @num_users = @users.count
31
+ log_task_info("Checking #{@num_users} users...")
32
+ end
33
+
34
+ def total_items
35
+ @num_users
36
+ end
37
+
38
+ # rubocop:disable Metrics/AbcSize
39
+ def do_execution(context)
40
+ progress_bar = context[:progress_bar]
41
+ CSV.open("spam_users.csv", "w") do |csv|
42
+ csv_headers = ["ID", "Is suspicious?", "Name", "Email", "Nickname", "Personal URL", "About",
43
+ "Organization ID", "Organization Name"]
44
+ csv << csv_headers
45
+
46
+ @users.find_each do |user|
47
+ suspicious = "NO"
48
+
49
+ if spam_user?(user)
50
+ suspicious = "YES"
51
+ @num_applied+= 1
52
+ end
53
+
54
+ csv << [user.id, suspicious, user.name, user.email, user.nickname, user.personal_url, user.about,
55
+ user.organization.id, user.organization.name]
56
+
57
+ progress_bar.increment
58
+ end
59
+ end
60
+ end
61
+ # rubocop:enable Metrics/AbcSize
62
+
63
+ def end_execution(_ctx)
64
+ if @num_applied.positive?
65
+ log_task_step("#{@num_applied} suspicious users")
66
+ log_task_step("Suspicious users list exported to spam_users.csv")
67
+ else
68
+ log_task_step("There are not suspicious users!!")
69
+ end
70
+ end
71
+
72
+ def spam_user?(user)
73
+ has_spam_word?(user) || has_spam_url?(user)
74
+ end
75
+
76
+ private
77
+
78
+ def has_spam_word?(user)
79
+ [user.name, user.about, user.nickname,
80
+ user.personal_url, user.about].compact.join("||").match?(Decidim::Cdtb.config.spam_regexp)
81
+ end
82
+
83
+ def has_spam_url?(user)
84
+ !!(user&.about =~ URL_REGEX || user.name =~ URL_REGEX)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -3,7 +3,9 @@
3
3
  require "decidim/cdtb/tasks_utils"
4
4
  require "decidim/cdtb/task"
5
5
  require "decidim/cdtb/fixes/nickname_fixer"
6
+ require "decidim/cdtb/users/remover"
6
7
  require "decidim/cdtb/multitenants/org_by_host_like"
8
+ require "decidim/cdtb/spam/user_spam_detector"
7
9
  require "decidim/cdtb/storage/local_sharding"
8
10
  require "decidim/cdtb/storage/set_local_on_blobs"
9
11
  require "decidim/cdtb/upgrades/validate_migrations_task"
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Cdtb
5
+ module Users
6
+ # Remove Decidim::User's
7
+ #
8
+ class Remover < ::Decidim::Cdtb::Task
9
+ def initialize(csv_path)
10
+ @csv_path = csv_path
11
+ progress_bar = { title: "Decidim::User" }
12
+ super("USER REMOVER", progress_bar: progress_bar)
13
+ end
14
+
15
+ def prepare_execution(_ctx); end
16
+
17
+ def total_items
18
+ File.open(@csv_path).readlines.size - 1
19
+ end
20
+
21
+ def do_execution(context)
22
+ progress_bar = context[:progress_bar]
23
+
24
+ CSV.foreach(@csv_path, headers: true, col_sep: ",") do |row|
25
+ user = Decidim::User.find_by(id: row[0])
26
+ next unless user.present?
27
+
28
+ reporter_user = Decidim::User.find_by(email: "support@coditramuntana.com",
29
+ organization: user.organization)
30
+ comments = Decidim::Comments::Comment.where(decidim_author_id: user.id)
31
+ manage_comments(comments, reporter_user) unless comments.empty?
32
+ destroy_user(user) if block_user(user, reporter_user)
33
+ progress_bar.increment
34
+ end
35
+ end
36
+
37
+ def end_execution(_ctx)
38
+ log_task_step("#{@num_applied} users removed")
39
+ end
40
+
41
+ private
42
+
43
+ def manage_comments(comments, reporter_user)
44
+ comments.find_each do |comment|
45
+ report_comment(comment, reporter_user)
46
+ hide_comment(comment, reporter_user)
47
+ end
48
+ end
49
+
50
+ def block_user(user, reporter_user)
51
+ params = {
52
+ user_id: user.id,
53
+ justification: "Confirmed spam suspicious"
54
+ }
55
+
56
+ form = Decidim::Admin::BlockUserForm.from_params(params).with_context(
57
+ {
58
+ current_organization: user.organization,
59
+ current_user: reporter_user
60
+ }
61
+ )
62
+
63
+ Decidim::Admin::BlockUser.call(form) do
64
+ on(:ok) do
65
+ puts "OK: User #{user.id} blocked"
66
+ return true
67
+ end
68
+
69
+ on(:invalid) do
70
+ puts "ERROR: User #{user.id} not blocked"
71
+ return false
72
+ end
73
+ end
74
+ end
75
+
76
+ def destroy_user(user)
77
+ params = {
78
+ delete_reason: "Confirmed spam suspicious"
79
+ }
80
+
81
+ form = Decidim::DeleteAccountForm.from_params(params)
82
+
83
+ Decidim::DestroyAccount.call(user, form) do
84
+ on(:ok) do
85
+ puts "OK: User #{user.id} removed"
86
+ end
87
+
88
+ on(:invalid) do
89
+ puts "ERROR: User #{user.id} not removed"
90
+ end
91
+ end
92
+ end
93
+
94
+ def report_comment(comment, reporter_user)
95
+ params = {
96
+ reason: "spam",
97
+ details: "Spam message"
98
+ }
99
+
100
+ form = Decidim::ReportForm.from_params(params)
101
+
102
+ CreateReport.call(form, comment, reporter_user) do
103
+ on(:ok) do
104
+ puts "OK: Comment #{comment.id} of User #{user.id} reported"
105
+ end
106
+
107
+ on(:invalid) do
108
+ puts "ERROR: Comment #{comment.id} of User #{user.id} not reported"
109
+ end
110
+ end
111
+ end
112
+
113
+ def hide_comment(comment, reporter_user)
114
+ Admin::HideResource.call(comment, reporter_user) do
115
+ on(:ok) do
116
+ puts "OK: Comment #{comment.id} of User #{user.id} hided"
117
+ end
118
+
119
+ on(:invalid) do
120
+ puts "ERROR: Comment #{comment.id} of User #{user.id} not hided"
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Decidim
4
4
  module Cdtb
5
- VERSION = "0.1.3"
5
+ VERSION = "0.1.6"
6
6
  DECIDIM_MIN_VERSION = ">= 0.26.2"
7
7
  end
8
8
  end
data/lib/decidim/cdtb.rb CHANGED
@@ -5,7 +5,14 @@ require_relative "cdtb/engine"
5
5
  require_relative "cdtb/tasks"
6
6
 
7
7
  module Decidim
8
+ # Cdtb configuration
8
9
  module Cdtb
10
+ include ActiveSupport::Configurable
11
+
9
12
  class Error < StandardError; end
13
+
14
+ config_accessor :spam_words do
15
+ %w[viagra sex game free crypto crack xxx luck girls vip download]
16
+ end
10
17
  end
11
18
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :cdtb do
4
+ namespace :spam do
5
+ desc "Show a list with users suspected of spam"
6
+ task :users, %i[org_id] => :environment do |_task, args|
7
+ organization = args.org_id.present? ? Decidim::Organization.find(args.org_id) : nil
8
+
9
+ detector = ::Decidim::Cdtb::Spam::UserSpamDetector.new(organization)
10
+ detector.execute!
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/cdtb/tasks"
4
+
5
+ namespace :cdtb do
6
+ namespace :users do
7
+ desc <<~EODESC
8
+ Fix Decidim::User's nicknames.
9
+ EODESC
10
+ task fix_nicknames: [:environment] do
11
+ fixer= ::Decidim::Cdtb::Fixes::NicknameFixer.new
12
+ fixer.execute!
13
+ end
14
+
15
+ desc <<~EODESC
16
+ Remove Decidim::User's by IDs in a CSV.
17
+ EODESC
18
+ task :remove, %i[csv_file] => [:environment] do |_taks, args|
19
+ service = ::Decidim::Cdtb::Users::Remover.new(args.csv_file)
20
+ service.execute!
21
+ end
22
+ end
23
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-cdtb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oliver Valls
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-10 00:00:00.000000000 Z
11
+ date: 2024-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: decidim
@@ -105,6 +105,7 @@ files:
105
105
  - lib/decidim/cdtb/engine.rb
106
106
  - lib/decidim/cdtb/fixes/nickname_fixer.rb
107
107
  - lib/decidim/cdtb/multitenants/org_by_host_like.rb
108
+ - lib/decidim/cdtb/spam/user_spam_detector.rb
108
109
  - lib/decidim/cdtb/storage/local_sharding.rb
109
110
  - lib/decidim/cdtb/storage/set_local_on_blobs.rb
110
111
  - lib/decidim/cdtb/task.rb
@@ -113,23 +114,25 @@ files:
113
114
  - lib/decidim/cdtb/upgrades/install_gem_migrations_step.rb
114
115
  - lib/decidim/cdtb/upgrades/upgrade_modules_task.rb
115
116
  - lib/decidim/cdtb/upgrades/validate_migrations_task.rb
117
+ - lib/decidim/cdtb/users/remover.rb
116
118
  - lib/decidim/cdtb/version.rb
117
119
  - lib/generators/cdtb/USAGE
118
120
  - lib/generators/cdtb/templates/validate_migrations.yml
119
121
  - lib/generators/cdtb/validate_migrations_ci_generator.rb
120
122
  - lib/tasks/anonymize.rake
121
- - lib/tasks/cdtb.rake
122
123
  - lib/tasks/multitenants.rake
124
+ - lib/tasks/spam.rake
123
125
  - lib/tasks/storage.rake
124
126
  - lib/tasks/upgrade.rake
127
+ - lib/tasks/users.rake
125
128
  - sig/decidim/cdtb.rbs
126
- homepage: http://github.com/CodiTramunana/cdtb
129
+ homepage: https://github.com/CodiTramuntana/decidim-module-cdtb
127
130
  licenses:
128
131
  - MIT
129
132
  metadata:
130
- homepage_uri: http://github.com/CodiTramunana/cdtb
131
- source_code_uri: http://github.com/CodiTramunana/cdtb
132
- changelog_uri: http://github.com/CodiTramunana/cdtb/CHANGELOG.md
133
+ homepage_uri: https://github.com/CodiTramuntana/decidim-module-cdtb
134
+ source_code_uri: https://github.com/CodiTramuntana/decidim-module-cdtb
135
+ changelog_uri: https://github.com/CodiTramuntana/decidim-module-cdtb/CHANGELOG.md
133
136
  post_install_message:
134
137
  rdoc_options: []
135
138
  require_paths:
data/lib/tasks/cdtb.rake DELETED
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "decidim/cdtb/tasks"
4
-
5
- namespace :cdtb do
6
- desc <<~EODESC
7
- Fix Decidim::User's nicknames.
8
- EODESC
9
- task fix_nicknames: [:environment] do
10
- fixer= ::Decidim::Cdtb::Fixes::NicknameFixer.new
11
- fixer.execute!
12
- end
13
- end