form_guard 0.1.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 +7 -0
- data/CHANGELOG.md +1 -0
- data/LICENSE.txt +21 -0
- data/README.md +38 -0
- data/Rakefile +12 -0
- data/lib/form_guard/controller.rb +28 -0
- data/lib/form_guard/railtie.rb +17 -0
- data/lib/form_guard/version.rb +3 -0
- data/lib/form_guard/view_helper.rb +16 -0
- data/lib/form_guard.rb +29 -0
- data/test/test_form_guard.rb +29 -0
- data/test/test_helper.rb +24 -0
- metadata +141 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4c52f84444c765efffe63b1be6771ba9a8bfcbbe077d2809f38935b66a03fa32
|
4
|
+
data.tar.gz: 9081dfd61917416bc8cb83b79919e3c93930bee9e637513458a2f777d0202283
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f6a81703c40d8e923fe7bd52163f8d3ca8e4267543c0386904bfbf21908bdf3789a64c75a5dacb89e8ab620f6744ee370ecad456f26672fa20d512f7cae64aff
|
7
|
+
data.tar.gz: 4438c1d1000c698a989c84911ec4c803dd74e67a4f63621dc43a8fd8fde4eace8ef56e52231c36f64e8690d53631980a0ff99ca4fec827f4be4261f82f45d8bc
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
## [Unreleased]
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 Stoyan Nikolov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Form Guard
|
2
|
+
|
3
|
+
Form Guard is a lightweight gem to protect your forms from bots and spammy submissions using a simple and effective honeypot + timing strategy.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
gem 'form_guard'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
bundle install
|
17
|
+
```
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
1. Add hidden guard field to your forms:
|
22
|
+
```bash
|
23
|
+
<%= form_guard_fields %>
|
24
|
+
```
|
25
|
+
|
26
|
+
## How it works
|
27
|
+
|
28
|
+
- Bots tend to fill all fields — including hidden ones. If the honeypot is filled, the submission is rejected.
|
29
|
+
|
30
|
+
- Bots submit instantly. If the form is submitted too quickly (under 2 seconds), it’s probably a bot.
|
31
|
+
|
32
|
+
## Contributing
|
33
|
+
|
34
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/amigobg/form_guard.
|
35
|
+
|
36
|
+
## License
|
37
|
+
|
38
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "active_support/concern"
|
2
|
+
|
3
|
+
module FormGuard
|
4
|
+
module Controller
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_action :verify_honeypot!
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
def verify_honeypot!
|
13
|
+
return unless request.post? || request.patch? || request.put?
|
14
|
+
|
15
|
+
config = FormGuard.configuration
|
16
|
+
min_delay = config.min_delay
|
17
|
+
|
18
|
+
raw_params = params.to_unsafe_h
|
19
|
+
|
20
|
+
honeypot_value = raw_params.find { |key, _| key.start_with?(config.honeypot_field_prefix) }&.last
|
21
|
+
honeypot_time = raw_params.find { |key, _| key.start_with?(config.honeypot_time_prefix) }&.last.to_i
|
22
|
+
|
23
|
+
if honeypot_value.present? || honeypot_time <= 0 || (Time.now.to_i - honeypot_time) < min_delay
|
24
|
+
redirect_to root_path, alert: "Suspicious activity detected"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rails/railtie"
|
2
|
+
|
3
|
+
module FormGuard
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
initializer "form_guard.action_view_integration" do
|
6
|
+
ActiveSupport.on_load(:action_view, run_once: true) do
|
7
|
+
include FormGuard::ViewHelper if defined?(ActionView)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
initializer "form_guard.action_controller_integration" do
|
12
|
+
ActiveSupport.on_load(:action_controller, run_once: true) do
|
13
|
+
include FormGuard::Controller if defined?(ActionController)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "securerandom"
|
2
|
+
|
3
|
+
module FormGuard
|
4
|
+
module ViewHelper
|
5
|
+
def form_guard_fields
|
6
|
+
config = FormGuard.configuration
|
7
|
+
|
8
|
+
tag.div style: "display:none;", "aria-hidden": "true" do
|
9
|
+
safe_join([
|
10
|
+
hidden_field_tag("#{config.honeypot_field_prefix}#{SecureRandom.hex(4)}", nil, autocomplete: "off"),
|
11
|
+
hidden_field_tag( "#{config.honeypot_time_prefix}#{SecureRandom.hex(4)}", Time.now.to_i, autocomplete: "off")
|
12
|
+
])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/form_guard.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "form_guard/version"
|
2
|
+
require_relative "form_guard/view_helper"
|
3
|
+
require_relative "form_guard/controller"
|
4
|
+
require_relative "form_guard/railtie"
|
5
|
+
|
6
|
+
module FormGuard
|
7
|
+
class Error < StandardError; end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_accessor :configuration
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.configure
|
14
|
+
self.configuration ||= Configuration.new
|
15
|
+
yield(configuration)
|
16
|
+
end
|
17
|
+
|
18
|
+
class Configuration
|
19
|
+
attr_accessor :min_delay, :honeypot_field_prefix, :honeypot_time_prefix
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@min_delay = 2
|
23
|
+
@honeypot_field_prefix = "field_"
|
24
|
+
@honeypot_time_prefix = "ts_"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
FormGuard.configuration ||= FormGuard::Configuration.new
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
|
5
|
+
class TestFormGuard < Minitest::Test
|
6
|
+
def test_that_it_has_a_version_number
|
7
|
+
refute_nil ::FormGuard::VERSION
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_it_has_default_configuration
|
11
|
+
config = FormGuard.configuration
|
12
|
+
assert_equal 2, config.min_delay
|
13
|
+
assert_equal "field_", config.honeypot_field_prefix
|
14
|
+
assert_equal "ts_", config.honeypot_time_prefix
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_configure_changes_settings
|
18
|
+
FormGuard.configure do |config|
|
19
|
+
config.min_delay = 5
|
20
|
+
config.honeypot_field_prefix = "hp_"
|
21
|
+
config.honeypot_time_prefix = "time_"
|
22
|
+
end
|
23
|
+
|
24
|
+
config = FormGuard.configuration
|
25
|
+
assert_equal 5, config.min_delay
|
26
|
+
assert_equal "hp_", config.honeypot_field_prefix
|
27
|
+
assert_equal "time_", config.honeypot_time_prefix
|
28
|
+
end
|
29
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "minitest/autorun"
|
5
|
+
require "mocha/minitest"
|
6
|
+
require "rails"
|
7
|
+
require "action_controller"
|
8
|
+
require "action_view"
|
9
|
+
require "form_guard"
|
10
|
+
|
11
|
+
class TestController < ActionController::Base
|
12
|
+
include FormGuard::Controller
|
13
|
+
end
|
14
|
+
|
15
|
+
class TestViewContext
|
16
|
+
include ActionView::Helpers::FormTagHelper
|
17
|
+
include ActionView::Helpers::TagHelper
|
18
|
+
include ActionView::Context
|
19
|
+
include FormGuard::ViewHelper
|
20
|
+
|
21
|
+
def root_path
|
22
|
+
"/"
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: form_guard
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stoyan Nikolov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-06-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '8.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '6.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '8.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: activesupport
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '6.0'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '8.0'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '6.0'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '8.0'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: minitest
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '5.16'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '5.16'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: actionpack
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '6.0'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '6.0'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: actionview
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '6.0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '6.0'
|
95
|
+
description: FormGuard provides a simple way to prevent bot form submissions in Rails
|
96
|
+
applications using honeypot fields and timestamp-based validation.
|
97
|
+
email:
|
98
|
+
- s.nikolov@roomspilot.com
|
99
|
+
executables: []
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- CHANGELOG.md
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- lib/form_guard.rb
|
108
|
+
- lib/form_guard/controller.rb
|
109
|
+
- lib/form_guard/railtie.rb
|
110
|
+
- lib/form_guard/version.rb
|
111
|
+
- lib/form_guard/view_helper.rb
|
112
|
+
- test/test_form_guard.rb
|
113
|
+
- test/test_helper.rb
|
114
|
+
homepage: https://github.com/amigobg/form_guard
|
115
|
+
licenses:
|
116
|
+
- MIT
|
117
|
+
metadata:
|
118
|
+
source_code_uri: https://github.com/amigobg/form_guard
|
119
|
+
changelog_uri: https://github.com/amigobg/form_guard/blob/master/CHANGELOG.md
|
120
|
+
bug_tracker_uri: https://github.com/amigobg/form_guard/issues
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: 3.0.0
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
requirements: []
|
136
|
+
rubygems_version: 3.5.22
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: A Rails gem to protect forms from bot submissions using honeypot and timestamp
|
140
|
+
checks.
|
141
|
+
test_files: []
|