decidim-cdtb 0.1.8 → 0.2.0
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 +4 -4
- data/.rubocop.yml +2 -2
- data/.ruby-version +1 -1
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +338 -306
- data/README.md +20 -2
- data/config/initializers/rack_attack.rb +28 -0
- data/decidim-cdtb.gemspec +2 -1
- data/lib/decidim/cdtb/spam/user_spam_detector.rb +4 -2
- data/lib/decidim/cdtb/version.rb +2 -2
- data/lib/tasks/anonymize.rake +2 -2
- data/lib/tasks/census.rake +78 -0
- data/lib/tasks/logs.rake +16 -0
- metadata +12 -8
data/README.md
CHANGED
@@ -65,17 +65,35 @@ To migrate from S3 to local storage, the identified steps will be:
|
|
65
65
|
`bin/rake cache:clear`
|
66
66
|
5. Restart the Rails server
|
67
67
|
|
68
|
-
###
|
68
|
+
### Spam & bots
|
69
69
|
|
70
|
-
|
70
|
+
Spam and bots are daily menaces in the current Internet. Decidim is not an exception, and is affected by both security concerns and performance.
|
71
|
+
|
72
|
+
#### Bad bots and crawlers
|
73
|
+
|
74
|
+
Decidim is already bundled with Rack::Attack but it lacks some features like IP banning or throttling by forwarded IP (useful when Decidim is behind a proxy). CDTB by default enables Rack::Attack with these features.
|
75
|
+
|
76
|
+
Four ENV variables exist to configure its behaviour:
|
77
|
+
|
78
|
+
- CDTB_RACK_ATTACK_DISABLED: Set to 1 to disable CDTB's Rack:Attack.
|
79
|
+
- RACK_ATTACK_THROTTLE_LIMIT: The max. allowed number of requests during the period. Defaults to 30.
|
80
|
+
- RACK_ATTACK_THROTTLE_PERIOD: The period in seconds. Defaults to 60.
|
81
|
+
- RACK_ATTACK_BLOCKED_IPS: A comma separated list of blocked IPs or subnets (in the form 1.2.3.0/32).
|
82
|
+
|
83
|
+
|
84
|
+
Available rake tasks to help analize crawlers:
|
85
|
+
|
86
|
+
- `bin/rake cdtb:logs:num_rq_per_ip` Counts the number of requests for each IP in the logs. Accepts a logfile param, it must be in log/.
|
71
87
|
|
72
88
|
#### Detect spam users
|
89
|
+
|
73
90
|
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
91
|
|
75
92
|
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
93
|
The columns in the CSV are: "ID, "Is suspicious?", "Name", "Email", "Nickname", "Personal URL", "About"
|
77
94
|
|
78
95
|
Examples:
|
96
|
+
|
79
97
|
`bin/rake cdtb:spam:users[org_id]` --> find users in organization with an id.
|
80
98
|
`bin/rake cdtb:spam:users` --> find all users in all organizations.
|
81
99
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
unless ENV["CDTB_RACK_ATTACK_DISABLED"].to_i.positive? || %w[development test].include?(Rails.env)
|
4
|
+
require "rack/attack"
|
5
|
+
|
6
|
+
limit= ENV.fetch("RACK_ATTACK_THROTTLE_LIMIT", 30)
|
7
|
+
period= ENV.fetch("RACK_ATTACK_THROTTLE_PERIOD", 60)
|
8
|
+
Rails.logger.info("Configuring Rack::Attack.throttle with limit: #{limit}, period: #{period}")
|
9
|
+
Rack::Attack.throttle("requests by (forwarded) ip", limit: limit.to_i, period: period.to_i) do |request|
|
10
|
+
# ignore requests to assets
|
11
|
+
next if request.path.start_with?("/rails/active_storage")
|
12
|
+
|
13
|
+
x_forwarded_for= request.get_header("HTTP_X_FORWARDED_FOR")
|
14
|
+
Rails.logger.info { ">>>>>>>>>>>>>>>>>>>> X-Forwarded-For: #{x_forwarded_for}" }
|
15
|
+
if x_forwarded_for.present?
|
16
|
+
ip= x_forwarded_for.split(":").first
|
17
|
+
ip
|
18
|
+
else
|
19
|
+
request.ip
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if ENV["RACK_ATTACK_BLOCKED_IPS"].present?
|
24
|
+
ENV["RACK_ATTACK_BLOCKED_IPS"].split(",").each do |ip_or_subnet|
|
25
|
+
Rack::Attack.blocklist_ip(ip_or_subnet)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/decidim-cdtb.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.description = "A gem to help managing Decidim applications."
|
13
13
|
spec.homepage = "https://github.com/CodiTramuntana/decidim-module-cdtb"
|
14
14
|
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">=
|
15
|
+
spec.required_ruby_version = ">= 3.0.7"
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
18
18
|
spec.metadata["source_code_uri"] = spec.homepage
|
@@ -35,4 +35,5 @@ Gem::Specification.new do |spec|
|
|
35
35
|
|
36
36
|
spec.add_development_dependency "decidim-dev", Decidim::Cdtb::DECIDIM_MIN_VERSION
|
37
37
|
spec.add_development_dependency "faker"
|
38
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
38
39
|
end
|
@@ -11,7 +11,7 @@ module Decidim
|
|
11
11
|
# rubocop:disable Style/RedundantRegexpEscape
|
12
12
|
URL_REGEX = %r{(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|
|
13
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,})}
|
14
|
+
(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})}
|
15
15
|
# rubocop:enable Style/RedundantRegexpEscape
|
16
16
|
|
17
17
|
def initialize(organization = nil)
|
@@ -40,7 +40,9 @@ module Decidim
|
|
40
40
|
# rubocop:disable Metrics/AbcSize
|
41
41
|
def do_execution(context)
|
42
42
|
progress_bar = context[:progress_bar]
|
43
|
-
|
43
|
+
filename= "spam_users.csv"
|
44
|
+
filepath= Rails.env.test? ? "tmp/#{filename}" : filename
|
45
|
+
CSV.open(filepath, "w") do |csv|
|
44
46
|
csv_headers = ["ID", "Is suspicious?", "Name", "Email", "Nickname", "Personal URL", "About",
|
45
47
|
"Organization ID", "Organization Name"]
|
46
48
|
csv << csv_headers
|
data/lib/decidim/cdtb/version.rb
CHANGED
data/lib/tasks/anonymize.rake
CHANGED
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/cdtb/tasks"
|
4
|
+
|
5
|
+
namespace :cdtb do
|
6
|
+
namespace :verifications do
|
7
|
+
desc <<~EODESC
|
8
|
+
Lists the verifications handlers in the current Decidim application.
|
9
|
+
EODESC
|
10
|
+
task handlers: :environment do |_task, _args|
|
11
|
+
puts "Verification Handlers in this Decidim application:"
|
12
|
+
Decidim.authorization_handlers.each do |manifest|
|
13
|
+
attrs= if manifest.form.present?
|
14
|
+
manifest.form.constantize.attribute_set.to_a.map(&:name).excluding(:id, :user, :handler_name).join(", ")
|
15
|
+
else
|
16
|
+
"No form."
|
17
|
+
end
|
18
|
+
puts "- #{manifest.name}: (#{attrs})"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc <<~EODESC
|
23
|
+
Returns the unique_id version of the given arguments for the given authorization handler.
|
24
|
+
Params:
|
25
|
+
- handler_name
|
26
|
+
- (optional) organization_id
|
27
|
+
- credential_1, credential_2, ...: in the form "id_document:00000000T", "birthdate:24/03/1977".
|
28
|
+
For example:
|
29
|
+
`bin/rake cdtb:verifications:to_unique_id[file_authorization_handler,id_document:00000000T,birthdate:01/01/2000]
|
30
|
+
`
|
31
|
+
EODESC
|
32
|
+
task :to_unique_id, [:handler_name] => :environment do |_task, args|
|
33
|
+
puts "Resolving #{args.handler_name} form class"
|
34
|
+
handler= find_handler_by_name(args.handler_name)
|
35
|
+
puts "Found handler with form class: #{handler.class}"
|
36
|
+
|
37
|
+
fill_handler_args(handler, args)
|
38
|
+
|
39
|
+
puts "unique_id: #{handler.unique_id}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def find_handler_by_name(handler_name)
|
43
|
+
handler_class= Decidim::Verifications.find_workflow_manifest(handler_name).form
|
44
|
+
handler_class.constantize.new
|
45
|
+
end
|
46
|
+
|
47
|
+
def fill_handler_args(handler, args)
|
48
|
+
arguments= args.to_a[1..]
|
49
|
+
current_organization= if arguments.first.include?(":")
|
50
|
+
Decidim::Organization.first
|
51
|
+
else
|
52
|
+
Decidim::Organization.find(arguments.first)
|
53
|
+
end
|
54
|
+
handler.with_context(current_organization: current_organization)
|
55
|
+
|
56
|
+
credentials= arguments.map { |arg| arg.split(":") }
|
57
|
+
puts "Setting credentials: #{credentials}"
|
58
|
+
credentials.each do |attr, val|
|
59
|
+
handler.send("#{attr}=".to_sym, val)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
desc <<~EODESC
|
64
|
+
Checks the given credentials against the specified verification handler. Params [handler_name,credential1,credential2,...]"
|
65
|
+
EODESC
|
66
|
+
task :census_check, [:handler_name] => :environment do |_task, args|
|
67
|
+
handler= find_handler_by_name(args.handler_name)
|
68
|
+
fill_handler_args(handler, args)
|
69
|
+
raise "This handler does not support Cdtb's verification_service" unless handler.respond_to?(:verification_service)
|
70
|
+
|
71
|
+
service= handler.verification_service
|
72
|
+
puts "Invoking #{service.class.name}..."
|
73
|
+
rs= service.send_request
|
74
|
+
puts "Response Ok?: #{service.rs_ok?}"
|
75
|
+
puts "RS: #{rs.body}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/tasks/logs.rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :cdtb do
|
4
|
+
namespace :logs do
|
5
|
+
desc "Analize logs in Rails format. Counts the number of requests for each IP in the logs. Accepts a logfile param, it must be in log/."
|
6
|
+
task :num_rq_per_ip, [:logfile] do |_task, args|
|
7
|
+
logfile= args.logfile || "development.log"
|
8
|
+
|
9
|
+
file_path= "log/#{logfile}"
|
10
|
+
first_cmd= "grep Started"
|
11
|
+
piped_cmds= [%(grep " for "), "cut -d ' ' -f13", "sort", "uniq -c", "sort"].join(" | ")
|
12
|
+
puts "Running: `#{first_cmd} #{file_path} | #{piped_cmds}`"
|
13
|
+
puts `#{first_cmd} #{file_path} | #{piped_cmds}`
|
14
|
+
end
|
15
|
+
end
|
16
|
+
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.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oliver Valls
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: decidim
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.27.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.27.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rails
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.
|
61
|
+
version: 0.27.0
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.
|
68
|
+
version: 0.27.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: faker
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- Rakefile
|
101
101
|
- app/jobs/application_job.rb
|
102
102
|
- app/jobs/cdtb/fix_nickname_job.rb
|
103
|
+
- config/initializers/rack_attack.rb
|
103
104
|
- decidim-cdtb.gemspec
|
104
105
|
- lib/decidim/cdtb.rb
|
105
106
|
- lib/decidim/cdtb/engine.rb
|
@@ -120,6 +121,8 @@ files:
|
|
120
121
|
- lib/generators/cdtb/templates/validate_migrations.yml
|
121
122
|
- lib/generators/cdtb/validate_migrations_ci_generator.rb
|
122
123
|
- lib/tasks/anonymize.rake
|
124
|
+
- lib/tasks/census.rake
|
125
|
+
- lib/tasks/logs.rake
|
123
126
|
- lib/tasks/multitenants.rake
|
124
127
|
- lib/tasks/spam.rake
|
125
128
|
- lib/tasks/storage.rake
|
@@ -133,6 +136,7 @@ metadata:
|
|
133
136
|
homepage_uri: https://github.com/CodiTramuntana/decidim-module-cdtb
|
134
137
|
source_code_uri: https://github.com/CodiTramuntana/decidim-module-cdtb
|
135
138
|
changelog_uri: https://github.com/CodiTramuntana/decidim-module-cdtb/CHANGELOG.md
|
139
|
+
rubygems_mfa_required: 'true'
|
136
140
|
post_install_message:
|
137
141
|
rdoc_options: []
|
138
142
|
require_paths:
|
@@ -141,14 +145,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
141
145
|
requirements:
|
142
146
|
- - ">="
|
143
147
|
- !ruby/object:Gem::Version
|
144
|
-
version:
|
148
|
+
version: 3.0.7
|
145
149
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
150
|
requirements:
|
147
151
|
- - ">="
|
148
152
|
- !ruby/object:Gem::Version
|
149
153
|
version: '0'
|
150
154
|
requirements: []
|
151
|
-
rubygems_version: 3.
|
155
|
+
rubygems_version: 3.2.33
|
152
156
|
signing_key:
|
153
157
|
specification_version: 4
|
154
158
|
summary: CodiTramuntana's Decidim Toolbelt (cdtb).
|