antispam 0.1.4 → 0.1.7

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: '06962cddbbfd16f9f59e18277630d9c597865483df7f72a5b33bdeccfab15c98'
4
- data.tar.gz: ce7b03a25d08d79271e61f7081d73922602c84201f7867d32a818fc9ff3b67e2
3
+ metadata.gz: 636c6cfd1e3a5c84182eaa1e19966e553a2098c4f3a01a049cdbe4613165a52e
4
+ data.tar.gz: 8a53d23ef78da214962bd81411a97a720d5eba3a15817d3f7ccd5bfac81719ec
5
5
  SHA512:
6
- metadata.gz: 63cb93116a4a5d5409ce5a6643071f5edc267f245251a97e06be683ec036126b245ca621c57656848812436a4761f3adc7c8e1980b451264a6942c3e8442d14b
7
- data.tar.gz: 04ca386da73cd5b9d273476ecbe624c1045f1d2933c58eab9bd4948b49806745d399b5aa4351d575ce9ad2bc75a945d8d4732336663bf13be7dd74972320dcf2
6
+ metadata.gz: b4d6e23e0432af6b62b7cd9e469c2393a9e4f4513b13d93d282e6841062bd706d70fa44dd6bed0d79658da80ff52827ee8ba9d63baa0a84df2112a7fd313b3dd
7
+ data.tar.gz: 9ca4921062395565e50fa29daf9d56bd3e691b5a675fb34bc4d6ec5e1378da1f3be5b19bdc73294be7fcb55b8e3d766819c140ef45b602d8904818eccf10f187
data/README.md CHANGED
@@ -1,72 +1,113 @@
1
- # Antispam
2
- The antispam gem helps prevent spam in your Rails applications by
3
- checking against various antispam blacklists on the web.
4
- You can configure which spam blacklists are checked in your application configuration.
5
-
6
- ## Usage
7
-
8
- The gem is used by adding this to your ApplicationController.rb
9
-
10
- ```
11
- before_action do
12
- check_ip_against_database(ip_blacklists: {default: 'yourcodehere'}, verbose: true)
13
- end
14
- ```
15
-
16
- Once the filter is setup, everything else is handled for your application.
17
- The gem will run during any request that is not a GET request.
18
-
19
- Blacklist database lookups are cached for 24 hours, and cached results won't need
20
- to slowdown your app by additional http requests on the backend.
21
-
22
- The gem needs to create some database tables to function; these store the cached
23
- blacklist database lookups, and any actions caused by the gem.
24
-
25
- You need to add this to your routes.rb
26
- ```
27
- mount Antispam::Engine => "/antispam"
28
- ```
29
- You can see what IP addresses have been blocked by going to /antispam/blocks
30
- but your applicationcontroller must respond to ```is_admin?``` function.
31
-
32
-
33
- ## Installation
34
- Add this line to your application's Gemfile:
35
-
36
- ```ruby
37
- gem 'antispam'
38
- ```
39
-
40
- And then execute:
41
- ```bash
42
- $ bundle
43
- ```
44
-
45
- Or install it yourself as:
46
- ```bash
47
- $ gem install antispam
48
- $ rails antispam:install:migrations
49
- $ rails db:migrate SCOPE=antispam
50
- ```
51
- The gem depends on image_processing, which depends on vips. We are using vips to
52
- generate captcha images.
53
- ```
54
- sudo apt install libvips-tools
55
- ```
56
-
57
- ## Development
58
-
59
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
60
-
61
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
62
-
63
- ## Contributing
64
-
65
- Bug reports and pull requests are welcome on GitHub at https://github.com/ryankopf/antispam. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/antispam/blob/master/CODE_OF_CONDUCT.md).
66
-
67
- ## License
68
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
69
-
70
- ## Code of Conduct
71
-
72
- Everyone interacting in the Antispam project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ryankopf/antispam/blob/master/CODE_OF_CONDUCT.md).
1
+ # Antispam
2
+ The antispam gem helps prevent spam in your Rails applications by
3
+ providing tools that check spam against powerful spam-prevention
4
+ databases, accessible for free.
5
+
6
+ The first feature checks against an IP database of spam, allowing you
7
+ to stop spammers who are prolific and have been detected on other websites.
8
+ It uses the blazing fast Defendium API to quickly determine if submitted
9
+ content is spam or not.
10
+
11
+ The second feature allows you to submit user-provided content to a spam
12
+ checking service that uses machine learning and a database of content to
13
+ determine whether the user's submitted content is spam.
14
+
15
+ ## Spam Content Checking - Usage
16
+
17
+ ```
18
+ result = Antispam::Checker.check(content: @comment.body)
19
+ if result.is_spam?
20
+ @comment.save
21
+ else
22
+ redirect_to "/access_denied"
23
+ end
24
+ ```
25
+
26
+ ## Bad IP Checking - Usage
27
+
28
+ The gem is used by adding this to your ApplicationController.rb
29
+
30
+ ```
31
+ before_action do
32
+ check_ip_against_database(ip_blacklists: {default: 'yourcodehere'}, verbose: true)
33
+ end
34
+ ```
35
+
36
+ Codes are from the [httpbl](https://www.projecthoneypot.org/httpbl.php) at projecthoneypot.org
37
+
38
+ Once the filter is setup, everything else is handled for your application.
39
+ By default the gem will run during any request that is not a GET request.
40
+
41
+ You can change the filter to run during other requests.
42
+
43
+ ```
44
+ before_action do
45
+ check_ip_against_database(ip_blacklists: {default: 'yourcodehere'}, methods: [:get,:post,:put,:patch,:delete])
46
+ end
47
+ ```
48
+
49
+ Blacklist database lookups are cached for 24 hours, and cached results won't need
50
+ to slowdown your app by additional http requests on the backend.
51
+
52
+ The gem needs to create some database tables to function; these store the cached
53
+ blacklist database lookups, and any actions caused by the gem.
54
+
55
+ You need to add this to your routes.rb
56
+ ```
57
+ mount Antispam::Engine => "/antispam"
58
+ ```
59
+ You can see what IP addresses have been blocked by going to /antispam/blocks
60
+ but your ApplicationController.rb must respond to ```is_admin?``` function.
61
+
62
+
63
+ ## Installation
64
+ Add this line to your application's Gemfile:
65
+
66
+ ```ruby
67
+ gem 'antispam'
68
+ ```
69
+
70
+ And then execute:
71
+ ```bash
72
+ $ bundle
73
+ ```
74
+
75
+ Or install it yourself as:
76
+ ```bash
77
+ $ gem install antispam
78
+ $ rails antispam:install:migrations
79
+ $ rails db:migrate SCOPE=antispam
80
+ ```
81
+ The gem depends on image_processing, which depends on vips. We are using vips to
82
+ generate captcha images.
83
+ ```
84
+ sudo apt install libvips-tools
85
+ ```
86
+
87
+ ## Development
88
+
89
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
90
+
91
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
92
+
93
+ ## Contributing
94
+
95
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ryankopf/antispam. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/antispam/blob/master/CODE_OF_CONDUCT.md).
96
+
97
+ ## License
98
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
99
+
100
+ ## Code of Conduct
101
+
102
+ Everyone interacting in the Antispam project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ryankopf/antispam/blob/master/CODE_OF_CONDUCT.md).
103
+
104
+ ## NO WARRANTY
105
+
106
+ THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND,
107
+ EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO,
108
+ ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS,
109
+ ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
110
+ OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE
111
+ ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO
112
+ THE SUBJECT SOFTWARE. THIS SOFTWARE IS PROVIDED "AS IS." IF YOUR JURISDICTION
113
+ DOES NOT ALLOW THESE LIMITATIONS THEN YOU MAY NOT USE THE SOFTWARE.
@@ -1,11 +1,11 @@
1
- module Antispam
2
- class ApplicationController < ::ApplicationController
3
- def must_be_admin
4
- begin
5
- render plain: 'Not available.' unless is_admin?
6
- rescue
7
- render plain: 'Not available.'
8
- end
9
- end
10
- end
11
- end
1
+ module Antispam
2
+ class ApplicationController < ::ApplicationController
3
+ def must_be_admin
4
+ begin
5
+ render plain: 'Not available.' unless is_admin?
6
+ rescue
7
+ render plain: 'Not available.'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,28 +1,28 @@
1
- require_dependency "antispam/application_controller"
2
-
3
- module Antispam
4
- class BlocksController < ApplicationController
5
- before_action :must_be_admin
6
- before_action :set_block, only: [:show]
7
-
8
- # GET /blocks
9
- def index
10
- @blocks = Block.all
11
- end
12
-
13
- # GET /blocks/1
14
- def show
15
- end
16
-
17
- private
18
- # Use callbacks to share common setup or constraints between actions.
19
- def set_block
20
- @block = Block.find(params[:id])
21
- end
22
-
23
- # Only allow a list of trusted parameters through.
24
- def block_params
25
- params.require(:block).permit(:ip, :provider, :controllername, :actionname)
26
- end
27
- end
28
- end
1
+ require_dependency "antispam/application_controller"
2
+
3
+ module Antispam
4
+ class BlocksController < ApplicationController
5
+ before_action :must_be_admin
6
+ before_action :set_block, only: [:show]
7
+
8
+ # GET /blocks
9
+ def index
10
+ @blocks = Block.all
11
+ end
12
+
13
+ # GET /blocks/1
14
+ def show
15
+ end
16
+
17
+ private
18
+ # Use callbacks to share common setup or constraints between actions.
19
+ def set_block
20
+ @block = Block.find(params[:id])
21
+ end
22
+
23
+ # Only allow a list of trusted parameters through.
24
+ def block_params
25
+ params.require(:block).permit(:ip, :provider, :controllername, :actionname)
26
+ end
27
+ end
28
+ end
@@ -1,49 +1,50 @@
1
- require_dependency "antispam/application_controller"
2
-
3
- module Antispam
4
- class ChallengesController < ApplicationController
5
- before_action :set_challenge, only: [:show, :edit, :update, :destroy]
6
-
7
- # GET /challenges/1
8
- def show
9
- respond_to do |format|
10
- format.jpeg do
11
- image = @challenge.get_image
12
- render content_type: 'image/jpeg', plain: image.jpegsave_buffer
13
- end
14
- end
15
- end
16
-
17
- # GET /challenges/new
18
- def new
19
- # use in the future for changing code
20
- end
21
-
22
- # PATCH/PUT /challenges/1
23
- def update
24
- if @challenge.validate?(params[:challenge][:answer])
25
- a = Antispam::Ip.find_or_create_by(address: request.remote_ip, provider: 'httpbl')
26
- before = a.threat
27
- a.threat = [(a.threat || 0) - 25, 0].max
28
- c = Clear.create(ip: request.remote_ip, answer: params[:challenge][:answer], result: 'Passed', threat_before: before, threat_after: a.threat)
29
- a.expires_at = 1.hour.from_now
30
- a.save
31
- redirect_to '/'
32
- else
33
- c = Clear.create(ip: request.remote_ip, answer: params[:challenge][:answer], result: 'Failed')
34
- redirect_to '/antispam/validate', notice: 'Invalid answer.'
35
- end
36
- end
37
-
38
- private
39
- # Use callbacks to share common setup or constraints between actions.
40
- def set_challenge
41
- @challenge = Challenge.find(params[:id])
42
- end
43
-
44
- # Only allow a list of trusted parameters through.
45
- def challenge_params
46
- params.require(:challenge).permit(:answer, :code)
47
- end
48
- end
49
- end
1
+ require_dependency "antispam/application_controller"
2
+
3
+ module Antispam
4
+ class ChallengesController < ApplicationController
5
+ before_action :set_challenge, only: [:show, :edit, :update, :destroy]
6
+
7
+ # GET /challenges/1
8
+ def show
9
+ respond_to do |format|
10
+ format.jpeg do
11
+ image = @challenge.get_image
12
+ render content_type: 'image/jpeg', plain: image.jpegsave_buffer
13
+ end
14
+ end
15
+ end
16
+
17
+ # GET /challenges/new
18
+ def new
19
+ # use in the future for changing code
20
+ head :ok
21
+ end
22
+
23
+ # PATCH/PUT /challenges/1
24
+ def update
25
+ if @challenge.validate?(params[:challenge][:answer])
26
+ a = Antispam::Ip.find_or_create_by(address: request.remote_ip, provider: 'httpbl')
27
+ before = a.threat
28
+ a.threat = [(a.threat || 0) - 25, 0].max
29
+ c = Clear.create(ip: request.remote_ip, answer: params[:challenge][:answer], result: 'Passed', threat_before: before, threat_after: a.threat)
30
+ a.expires_at = 1.hour.from_now
31
+ a.save
32
+ redirect_to '/'
33
+ else
34
+ c = Clear.create(ip: request.remote_ip, answer: params[:challenge][:answer], result: 'Failed')
35
+ redirect_to '/antispam/validate', notice: 'Invalid answer.'
36
+ end
37
+ end
38
+
39
+ private
40
+ # Use callbacks to share common setup or constraints between actions.
41
+ def set_challenge
42
+ @challenge = Challenge.find(params[:id])
43
+ end
44
+
45
+ # Only allow a list of trusted parameters through.
46
+ def challenge_params
47
+ params.require(:challenge).permit(:answer, :code)
48
+ end
49
+ end
50
+ end
@@ -1,28 +1,28 @@
1
- require_dependency "antispam/application_controller"
2
-
3
- module Antispam
4
- class ClearsController < ApplicationController
5
- before_action :must_be_admin
6
- before_action :set_clear, only: [:show, :edit, :update, :destroy]
7
-
8
- # GET /clears
9
- def index
10
- @clears = Clear.all
11
- end
12
-
13
- # GET /clears/1
14
- def show
15
- end
16
-
17
- private
18
- # Use callbacks to share common setup or constraints between actions.
19
- def set_clear
20
- @clear = Clear.find(params[:id])
21
- end
22
-
23
- # Only allow a list of trusted parameters through.
24
- def clear_params
25
- params.require(:clear).permit(:ip, :result, :answer, :threat_before, :threat_after)
26
- end
27
- end
28
- end
1
+ require_dependency "antispam/application_controller"
2
+
3
+ module Antispam
4
+ class ClearsController < ApplicationController
5
+ before_action :must_be_admin
6
+ before_action :set_clear, only: [:show, :edit, :update, :destroy]
7
+
8
+ # GET /clears
9
+ def index
10
+ @clears = Clear.all
11
+ end
12
+
13
+ # GET /clears/1
14
+ def show
15
+ end
16
+
17
+ private
18
+ # Use callbacks to share common setup or constraints between actions.
19
+ def set_clear
20
+ @clear = Clear.find(params[:id])
21
+ end
22
+
23
+ # Only allow a list of trusted parameters through.
24
+ def clear_params
25
+ params.require(:clear).permit(:ip, :result, :answer, :threat_before, :threat_after)
26
+ end
27
+ end
28
+ end
@@ -1,39 +1,39 @@
1
- <p id="notice"><%= notice %></p>
2
-
3
- <div class="row">
4
- <div class="cx">
5
- <h1>Blocks</h1>
6
-
7
- <table>
8
- <thead>
9
- <tr>
10
- <th>Ip</th>
11
- <th>Provider</th>
12
- <th>Controllername</th>
13
- <th>Actionname</th>
14
- <th>Threat</th>
15
- <th colspan="3"></th>
16
- </tr>
17
- </thead>
18
-
19
- <tbody>
20
- <% Antispam::Block.all.order(created_at: :desc).limit(50).each do |block| %>
21
- <tr>
22
- <td><%= block.ip %></td>
23
- <td><%= block.provider %></td>
24
- <td><%= block.controllername %></td>
25
- <td><%= block.actionname %></td>
26
- <td><%= block.threat %></td>
27
- <td><%= time_ago_in_words block.created_at %> ago</td>
28
- <!-- <td><%#= link_to 'Show', block %></td>-->
29
- <!-- <td><%#= link_to 'Edit', edit_block_path(block) %></td>-->
30
- <!-- <td><%#= link_to 'Destroy', block, method: :delete, data: { confirm: 'Are you sure?' } %></td>-->
31
- </tr>
32
- <% end %>
33
- </tbody>
34
- </table>
35
- </div>
36
- <div class="cx">
37
- <%= render template: '/antispam/clears/index.html' %>
38
- </div>
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <div class="row">
4
+ <div class="cx">
5
+ <h1>Blocks</h1>
6
+
7
+ <table>
8
+ <thead>
9
+ <tr>
10
+ <th>Ip</th>
11
+ <th>Provider</th>
12
+ <th>Controllername</th>
13
+ <th>Actionname</th>
14
+ <th>Threat</th>
15
+ <th colspan="3"></th>
16
+ </tr>
17
+ </thead>
18
+
19
+ <tbody>
20
+ <% Antispam::Block.all.order(created_at: :desc).limit(50).each do |block| %>
21
+ <tr>
22
+ <td><%= block.ip %></td>
23
+ <td><%= block.provider %></td>
24
+ <td><%= block.controllername %></td>
25
+ <td><%= block.actionname %></td>
26
+ <td><%= block.threat %></td>
27
+ <td><%= time_ago_in_words block.created_at %> ago</td>
28
+ <!-- <td><%#= link_to 'Show', block %></td>-->
29
+ <!-- <td><%#= link_to 'Edit', edit_block_path(block) %></td>-->
30
+ <!-- <td><%#= link_to 'Destroy', block, method: :delete, data: { confirm: 'Are you sure?' } %></td>-->
31
+ </tr>
32
+ <% end %>
33
+ </tbody>
34
+ </table>
35
+ </div>
36
+ <div class="cx">
37
+ <%= render template: '/antispam/clears/index', formats: :html %>
38
+ </div>
39
39
  </div>
@@ -1,32 +1,32 @@
1
- <p id="notice"><%= notice %></p>
2
-
3
- <h1>Clears</h1>
4
-
5
- <table>
6
- <thead>
7
- <tr>
8
- <th>Ip</th>
9
- <th>Result</th>
10
- <th>Answer</th>
11
- <th>Threat before</th>
12
- <th>Threat after</th>
13
- <th colspan="3"></th>
14
- </tr>
15
- </thead>
16
-
17
- <tbody>
18
- <% Antispam::Clear.all.order(created_at: :desc).limit(50).each do |clear| %>
19
- <tr>
20
- <td><%= clear.ip %></td>
21
- <td><%= clear.result %></td>
22
- <td><%= clear.answer %></td>
23
- <td><%= clear.threat_before %></td>
24
- <td><%= clear.threat_after %></td>
25
- <td><%= time_ago_in_words clear.created_at %> ago</td>
26
- <!-- <td><%#= link_to 'Show', clear %></td>-->
27
- <!-- <td><%#= link_to 'Edit', edit_clear_path(clear) %></td>-->
28
- <!-- <td><%#= link_to 'Destroy', clear, method: :delete, data: { confirm: 'Are you sure?' } %></td>-->
29
- </tr>
30
- <% end %>
31
- </tbody>
32
- </table>
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <h1>Clears</h1>
4
+
5
+ <table>
6
+ <thead>
7
+ <tr>
8
+ <th>Ip</th>
9
+ <th>Result</th>
10
+ <th>Answer</th>
11
+ <th>Threat before</th>
12
+ <th>Threat after</th>
13
+ <th colspan="3"></th>
14
+ </tr>
15
+ </thead>
16
+
17
+ <tbody>
18
+ <% Antispam::Clear.all.order(created_at: :desc).limit(50).each do |clear| %>
19
+ <tr>
20
+ <td><%= clear.ip %></td>
21
+ <td><%= clear.result %></td>
22
+ <td><%= clear.answer %></td>
23
+ <td><%= clear.threat_before %></td>
24
+ <td><%= clear.threat_after %></td>
25
+ <td><%= time_ago_in_words clear.created_at %> ago</td>
26
+ <!-- <td><%#= link_to 'Show', clear %></td>-->
27
+ <!-- <td><%#= link_to 'Edit', edit_clear_path(clear) %></td>-->
28
+ <!-- <td><%#= link_to 'Destroy', clear, method: :delete, data: { confirm: 'Are you sure?' } %></td>-->
29
+ </tr>
30
+ <% end %>
31
+ </tbody>
32
+ </table>
@@ -1,15 +1,15 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>Antispam</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
7
- <style>.row { width:100%;display: flex;} .cx { width: 50%; }</style>
8
- <%#= stylesheet_link_tag "antispam/application", media: "all" %>
9
- </head>
10
- <body>
11
-
12
- <%= yield %>
13
-
14
- </body>
15
- </html>
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Antispam</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+ <style>.row { width:100%;display: flex;} .cx { width: 50%; }</style>
8
+ <%#= stylesheet_link_tag "antispam/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
@@ -1,5 +1,5 @@
1
- class AddThreatToAntispamBlocks < ActiveRecord::Migration[6.1]
2
- def change
3
- add_column :antispam_blocks, :threat, :integer
4
- end
5
- end
1
+ class AddThreatToAntispamBlocks < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :antispam_blocks, :threat, :integer
4
+ end
5
+ end
@@ -2,28 +2,33 @@ require 'resolv'
2
2
  module Antispam
3
3
  module Blacklists
4
4
  class Httpbl
5
- def self.check(ip, key)
5
+ def self.check(ip, key, verbose)
6
6
  threat = 0
7
7
  begin
8
- return get_old_result(ip) if get_old_result(ip)
8
+ old_result = get_old_result(ip)
9
+ if old_result
10
+ Rails.logger.info "Returning old result for #{ip}." if verbose
11
+ return get_old_result(ip)
12
+ end
9
13
  check = ip.split('.').reverse.join('.')
10
14
  host = key + '.' + check + ".dnsbl.httpbl.org"
11
15
  address = Resolv::getaddress(host)
12
16
  z,days,threat,iptype = address.split('.')
13
- Rails.logger.info "Spam located: #{iptype} type at #{threat} threat. (#{ip} - #{address})"
17
+ Rails.logger.info "Spam located: #{iptype} type at #{threat} threat. (#{ip} - #{address})" if verbose
18
+ threat = threat.to_i
14
19
  # Create or update
15
- if (threat.to_i > 30)
16
- Rails.logger.info "Spamcheck: Very high, over 30!"
20
+ if (threat > 30)
21
+ Rails.logger.info "Spamcheck: Very high, over 30!" if verbose
17
22
  end
18
23
  rescue Exception => e
19
24
  case e
20
25
  when Resolv::ResolvError #Not spam! This blacklist gives an error when there's no spam threat.
21
- Rails.logger.info "Spamcheck: OK! Resolve error means the httpbl does not consider this spam."
26
+ Rails.logger.info "Spamcheck: OK! Resolve error means the httpbl does not consider this spam." if verbose
22
27
  when Interrupt #Something broke while trying to check blacklist.
23
- Rails.logger.info "Spamcheck: Interrupt when trying to resolve http blacklist. Possible timeout?"
28
+ Rails.logger.info "Spamcheck: Interrupt when trying to resolve http blacklist. Possible timeout?" if verbose
24
29
  else # Time Out
25
- Rails.logger.info "Spamcheck: There was an error, possibly a time out, when checking this IP."
26
- Rails.logger.info e.to_s
30
+ Rails.logger.info "Spamcheck: There was an error, possibly a time out, when checking this IP." if verbose
31
+ Rails.logger.info e.to_s if verbose
27
32
  end
28
33
  end
29
34
  update_old_result(ip, threat)
@@ -0,0 +1,20 @@
1
+ module Antispam
2
+ module Checker
3
+ # Checks content for spam
4
+ # check(options, spamcheck_providers)
5
+ # Usage: check({content: "No spam here"}, {defendium: 'MY_API_KEY'}})
6
+ def self.check(options = {}, spamcheck_providers = {defendium: 'YOUR_KEY'})
7
+ Rails.logger.info "Content was nil for spamcheck." if options[:content].nil? && options[:verbose]
8
+ return if options[:content].nil?
9
+ Rails.logger.info "Spamcheckers should be a hash" if (!(options[:spamcheck_providers].is_a? Hash)) && options[:verbose]
10
+ results = []
11
+ spamcheck_providers.each do |spamchecker_name, spamchecker_api_key|
12
+ if spamchecker_name == :defendium
13
+ results.append Antispam::Spamcheckers::Defendium.check(options[:content], spamchecker_api_key, options[:verbose])
14
+ end
15
+ end
16
+ result = Antispam::SpamcheckResult.new(results)
17
+ return result
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ module Antispam
2
+ class SpamcheckResult
3
+ def initialize(results)
4
+ @results = results
5
+ end
6
+ def is_spam?
7
+ @results.select{|x| x > 0}.present?
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ #require 'resolv'
2
+ module Antispam
3
+ module Spamcheckers
4
+ class Defendium
5
+ def self.check(content, key, verbose)
6
+ # nethttp2.rb
7
+ require 'uri'
8
+ require 'net/http'
9
+
10
+ uri = URI('https://api.defendium.com/check')
11
+ params = { secret_key: key, content: content }
12
+ uri.query = URI.encode_www_form(params)
13
+
14
+ res = Net::HTTP.get_response(uri)
15
+ if res.is_a?(Net::HTTPSuccess)
16
+ result = res.body.to_json
17
+ if result["warnings"]
18
+ Rails.logger.info result["warnings"]
19
+ end
20
+ if result["result"]
21
+ return 1
22
+ else
23
+ return 0
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,48 +1,57 @@
1
- module Antispam
2
- module Tools
3
- # before_action :check_ip_against_database
4
- def check_ip_against_database(options = {ip_blacklists: {default: ''}})
5
- return if request.get?
6
- return if skip_if_user_whitelisted
7
- return if controller_name == "validate"
8
- ip = request.remote_ip
9
- # First, check IP blacklists.
10
- if (options[:ip_blacklists])
11
- if options[:ip_blacklists][:default]
12
- options[:ip_blacklists][:httpbl] = options[:ip_blacklists][:default]
13
- options[:ip_blacklists].delete(:default)
14
- end
15
- check_ip_against_blacklists(ip, options[:ip_blacklists], options[:verbose])
16
- end
17
- # Second, check for weird countries.
18
- if (options[:scrutinize_countries_except])
19
-
20
- end
21
- Rails.logger.info "Got to this function. #{ip}"
22
- puts "Got to this function. #{ip}"
23
- end
24
- def check_ip_against_blacklists(ip, lists, verbose)
25
- lists.each do |provider_name, provider_api_key|
26
- puts "Checking provider: #{provider_name}" if verbose
27
- if provider_name == :httpbl
28
- result = Antispam::Blacklists::Httpbl.check(ip, provider_api_key)
29
- puts result if verbose
30
- if (result > 30)
31
- Block.create(ip: ip, provider: provider_name, threat: result)
32
- redirect_to '/antispam/validate'
33
- end
34
- end
35
- end
36
- end
37
-
38
- def skip_if_user_whitelisted
39
- if respond_to? :current_user
40
- if current_user && current_user.respond_to?(:antispam_whitelisted?)
41
- return true if current_user.antispam_whitelisted?
42
- end
43
- end
44
- end
45
-
46
-
47
- end
48
- end
1
+ module Antispam
2
+ module Tools
3
+ # Checks spam against an IP database of spammers.
4
+ # Usage: before_action :check_ip_against_database
5
+ def check_ip_against_database(options = {ip_blacklists: {default: ''}})
6
+ if (options[:methods])
7
+ return if request.get? unless options[:methods].include?(:get)
8
+ return if request.post? unless options[:methods].include?(:post)
9
+ return if request.put? unless options[:methods].include?(:put)
10
+ return if request.patch? unless options[:methods].include?(:patch)
11
+ return if request.delete? unless options[:methods].include?(:delete)
12
+ else
13
+ return if request.get?
14
+ end
15
+ return if skip_if_user_whitelisted
16
+ return if controller_name == "validate"
17
+ ip = request.remote_ip
18
+ # First, check IP blacklists.
19
+ if (options[:ip_blacklists])
20
+ if options[:ip_blacklists][:default]
21
+ options[:ip_blacklists][:httpbl] = options[:ip_blacklists][:default]
22
+ options[:ip_blacklists].delete(:default)
23
+ end
24
+ check_ip_against_blacklists(ip, options[:ip_blacklists], options[:verbose])
25
+ end
26
+ # Second, check for weird countries.
27
+ if (options[:scrutinize_countries_except])
28
+
29
+ end
30
+ Rails.logger.info "Completed IP database check. #{ip}" if options[:verbose]
31
+ end
32
+ # Checks the specific blacklists
33
+ def check_ip_against_blacklists(ip, lists, verbose)
34
+ lists.each do |provider_name, provider_api_key|
35
+ Rails.logger.info "Checking provider: #{provider_name}" if verbose
36
+ if provider_name == :httpbl
37
+ result = Antispam::Blacklists::Httpbl.check(ip, provider_api_key, verbose)
38
+ Rails.logger.info(result) if verbose
39
+ if (result > 30)
40
+ Block.create(ip: ip, provider: provider_name, threat: result)
41
+ redirect_to '/antispam/validate'
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def skip_if_user_whitelisted
48
+ if respond_to? :current_user
49
+ if current_user && current_user.respond_to?(:antispam_whitelisted?)
50
+ return true if current_user.antispam_whitelisted?
51
+ end
52
+ end
53
+ end
54
+
55
+
56
+ end
57
+ end
@@ -1,3 +1,3 @@
1
- module Antispam
2
- VERSION = '0.1.4'
3
- end
1
+ module Antispam
2
+ VERSION = '0.1.7'
3
+ end
data/lib/antispam.rb CHANGED
@@ -1,11 +1,17 @@
1
- require "antispam/version"
2
- require "antispam/engine"
3
- require "antispam/tools"
4
- require "antispam/blacklists/httpbl"
5
-
6
- module Antispam
7
- ActiveSupport.on_load(:action_controller) do
8
- # self refers to ActionController::Base here
9
- self.include Antispam::Tools
10
- end
11
- end
1
+ require "antispam/version"
2
+ require "antispam/engine"
3
+ require "antispam/tools"
4
+ require "antispam/checker"
5
+ require "antispam/blacklists/httpbl"
6
+ require "antispam/spamcheckers/defendium"
7
+ require "antispam/results"
8
+
9
+ module Antispam
10
+ ActiveSupport.on_load(:action_controller) do
11
+ # self refers to ActionController::Base here
12
+ # This way is removed because below may be more compatible.
13
+ # self.include Antispam::Tools
14
+ # Would the below be a better (clearer? more compatible?) way to do this?
15
+ ActionController::Base.send(:include, Antispam::Tools)
16
+ end
17
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: antispam
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Kopf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-31 00:00:00.000000000 Z
11
+ date: 2023-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 6.0.0
19
+ version: 6.1.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: 6.0.0
26
+ version: 6.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: image_processing
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: net-http
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: Antispam checks DNS blacklists and helps prevent spam on your site.
42
56
  email:
43
57
  - antispam@ryankopf.com
@@ -83,20 +97,14 @@ files:
83
97
  - app/models/antispam/challenge.rb
84
98
  - app/models/antispam/clear.rb
85
99
  - app/models/antispam/ip.rb
86
- - app/views/antispam/blocks/_form.html.erb
87
- - app/views/antispam/blocks/edit.html.erb
88
100
  - app/views/antispam/blocks/index.html.erb
89
- - app/views/antispam/blocks/new.html.erb
90
101
  - app/views/antispam/blocks/show.html.erb
91
102
  - app/views/antispam/challenges/_form.html.erb
92
103
  - app/views/antispam/challenges/edit.html.erb
93
104
  - app/views/antispam/challenges/index.html.erb
94
105
  - app/views/antispam/challenges/new.html.erb
95
106
  - app/views/antispam/challenges/show.html.erb
96
- - app/views/antispam/clears/_form.html.erb
97
- - app/views/antispam/clears/edit.html.erb
98
107
  - app/views/antispam/clears/index.html.erb
99
- - app/views/antispam/clears/new.html.erb
100
108
  - app/views/antispam/clears/show.html.erb
101
109
  - app/views/antispam/validate/index.html.erb
102
110
  - app/views/layouts/antispam/application.html.erb
@@ -108,7 +116,10 @@ files:
108
116
  - db/migrate/20210131165122_add_threat_to_antispam_blocks.rb
109
117
  - lib/antispam.rb
110
118
  - lib/antispam/blacklists/httpbl.rb
119
+ - lib/antispam/checker.rb
111
120
  - lib/antispam/engine.rb
121
+ - lib/antispam/results.rb
122
+ - lib/antispam/spamcheckers/defendium.rb
112
123
  - lib/antispam/tools.rb
113
124
  - lib/antispam/version.rb
114
125
  - lib/tasks/antispam_tasks.rake
@@ -135,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
146
  - !ruby/object:Gem::Version
136
147
  version: '0'
137
148
  requirements: []
138
- rubygems_version: 3.1.4
149
+ rubygems_version: 3.4.4
139
150
  signing_key:
140
151
  specification_version: 4
141
152
  summary: A spam prevention gem.
@@ -1,37 +0,0 @@
1
- <%= form_with(model: block) do |form| %>
2
- <% if block.errors.any? %>
3
- <div id="error_explanation">
4
- <h2><%= pluralize(block.errors.count, "error") %> prohibited this block from being saved:</h2>
5
-
6
- <ul>
7
- <% block.errors.each do |error| %>
8
- <li><%= error.full_message %></li>
9
- <% end %>
10
- </ul>
11
- </div>
12
- <% end %>
13
-
14
- <div class="field">
15
- <%= form.label :ip %>
16
- <%= form.text_field :ip %>
17
- </div>
18
-
19
- <div class="field">
20
- <%= form.label :provider %>
21
- <%= form.text_field :provider %>
22
- </div>
23
-
24
- <div class="field">
25
- <%= form.label :controllername %>
26
- <%= form.text_field :controllername %>
27
- </div>
28
-
29
- <div class="field">
30
- <%= form.label :actionname %>
31
- <%= form.text_field :actionname %>
32
- </div>
33
-
34
- <div class="actions">
35
- <%= form.submit %>
36
- </div>
37
- <% end %>
@@ -1,6 +0,0 @@
1
- <h1>Editing Block</h1>
2
-
3
- <%= render 'form', block: @block %>
4
-
5
- <%= link_to 'Show', @block %> |
6
- <%= link_to 'Back', blocks_path %>
@@ -1,5 +0,0 @@
1
- <h1>New Block</h1>
2
-
3
- <%= render 'form', block: @block %>
4
-
5
- <%= link_to 'Back', blocks_path %>
@@ -1,42 +0,0 @@
1
- <%= form_with(model: clear) do |form| %>
2
- <% if clear.errors.any? %>
3
- <div id="error_explanation">
4
- <h2><%= pluralize(clear.errors.count, "error") %> prohibited this clear from being saved:</h2>
5
-
6
- <ul>
7
- <% clear.errors.each do |error| %>
8
- <li><%= error.full_message %></li>
9
- <% end %>
10
- </ul>
11
- </div>
12
- <% end %>
13
-
14
- <div class="field">
15
- <%= form.label :ip %>
16
- <%= form.text_field :ip %>
17
- </div>
18
-
19
- <div class="field">
20
- <%= form.label :result %>
21
- <%= form.text_field :result %>
22
- </div>
23
-
24
- <div class="field">
25
- <%= form.label :answer %>
26
- <%= form.text_field :answer %>
27
- </div>
28
-
29
- <div class="field">
30
- <%= form.label :threat_before %>
31
- <%= form.number_field :threat_before %>
32
- </div>
33
-
34
- <div class="field">
35
- <%= form.label :threat_after %>
36
- <%= form.number_field :threat_after %>
37
- </div>
38
-
39
- <div class="actions">
40
- <%= form.submit %>
41
- </div>
42
- <% end %>
@@ -1,6 +0,0 @@
1
- <h1>Editing Clear</h1>
2
-
3
- <%= render 'form', clear: @clear %>
4
-
5
- <%= link_to 'Show', @clear %> |
6
- <%= link_to 'Back', clears_path %>
@@ -1,5 +0,0 @@
1
- <h1>New Clear</h1>
2
-
3
- <%= render 'form', clear: @clear %>
4
-
5
- <%= link_to 'Back', clears_path %>