otori 0.1.0 → 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/CHANGELOG.md +13 -0
- data/README.md +59 -25
- data/lib/otori/rails.rb +56 -0
- data/lib/otori/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dad6a295086cd2eb7abd60f81e264cde80726e6802deec8e185b3d6ddd2bd082
|
|
4
|
+
data.tar.gz: b1fe5bab67f24f249b9b45055fa0a632774b99fa93fe0c156235014c9bdf1416
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a275bbc1f3a7ce4a3f8ae0b6a09b0835aeeca30713254819f747e3e3b06f0c2e8a875a6ca604a8df396ada100ce9518238e8575ec1a06a3bb06e2bec5abe8b5d
|
|
7
|
+
data.tar.gz: 7fee9a413435e3efcf65f5196fdffe168c664935c8e1390f06545cb9f650571e47e031f04f3f9f2649f01a0b62a67229a9e7071199bdc2903c3dfe1543e625f1
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.0] - 2026-09-17
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `Otori::Rails`, an optional adapter for Rails apps. Provides a
|
|
15
|
+
`honeypot` controller class macro that registers a `before_action`
|
|
16
|
+
(halting with `:no_content` by default, or running a user-supplied
|
|
17
|
+
block), and a `honeypot_field` / `honeypot_signals` view-helper pair.
|
|
18
|
+
Loaded via `require "otori/rails"`; auto-hooks via a Railtie when
|
|
19
|
+
present.
|
|
20
|
+
|
|
21
|
+
## [0.1.0] - 2026-05-22
|
|
22
|
+
|
|
10
23
|
### Added
|
|
11
24
|
|
|
12
25
|
- Initial scaffolding inspired by the
|
data/README.md
CHANGED
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
[](https://codeberg.org/fluck/otori/actions?workflow=ci.yml)
|
|
4
4
|
[](https://codeberg.org/fluck/otori/tags)
|
|
5
5
|
|
|
6
|
-
Invisible
|
|
7
|
-
|
|
6
|
+
Invisible honeypot spam protection for Hanami, Sinatra, Roda, Rails, and any
|
|
7
|
+
other Rack-based Ruby app. Think of it as a framework-agnostic
|
|
8
|
+
[invisible_captcha](https://github.com/markets/invisible_captcha) with a
|
|
9
|
+
first-class Hanami adapter and an extra layer of JavaScript-based input
|
|
10
|
+
detection.
|
|
8
11
|
|
|
9
12
|
_Otori_ (囮) is the Japanese word for "decoy", historically a bird used in
|
|
10
13
|
hunting to draw others in.
|
|
@@ -26,6 +29,29 @@ or flag submissions at a chosen _human rating_ threshold.
|
|
|
26
29
|
> [Codeberg](https://codeberg.org/fluck/otori). The [GitHub
|
|
27
30
|
> repo](https://github.com/flucksite/otori) is just a mirror.
|
|
28
31
|
|
|
32
|
+
## How it compares
|
|
33
|
+
|
|
34
|
+
### otori
|
|
35
|
+
|
|
36
|
+
- Frameworks: Hanami, Sinatra, Roda, Rails, any Rack app
|
|
37
|
+
- Hidden field + timing check + JS input signals
|
|
38
|
+
- Active (new in 2026)
|
|
39
|
+
|
|
40
|
+
### [invisible_captcha](https://github.com/markets/invisible_captcha)
|
|
41
|
+
|
|
42
|
+
- Frameworks: Rails only
|
|
43
|
+
- Hidden field + timing check
|
|
44
|
+
- Actively maintained
|
|
45
|
+
|
|
46
|
+
### [rack-honeypot](https://github.com/sunlightlabs/rack-honeypot)
|
|
47
|
+
|
|
48
|
+
- Frameworks: any Rack app
|
|
49
|
+
- Hidden field only
|
|
50
|
+
- Dormant since 2016
|
|
51
|
+
|
|
52
|
+
If you're on Rails and don't need the JS signals layer, `invisible_captcha` is
|
|
53
|
+
the more battle-tested choice. Otori exists for everything else.
|
|
54
|
+
|
|
29
55
|
## Installation
|
|
30
56
|
|
|
31
57
|
Add this to your Gemfile:
|
|
@@ -174,46 +200,54 @@ In the view:
|
|
|
174
200
|
|
|
175
201
|
### Rails
|
|
176
202
|
|
|
177
|
-
Rails
|
|
178
|
-
|
|
179
|
-
if you want the input-signals rating on top.
|
|
203
|
+
Load the Rails adapter from your Gemfile so the Railtie auto-hooks the
|
|
204
|
+
controller macros and view helpers:
|
|
180
205
|
|
|
181
206
|
```ruby
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
def honeypot_field(name, **attrs)
|
|
185
|
-
Otori.field(name, session: session, **attrs).html_safe
|
|
186
|
-
end
|
|
207
|
+
gem "otori", require: "otori/rails"
|
|
208
|
+
```
|
|
187
209
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
210
|
+
In a form template:
|
|
211
|
+
|
|
212
|
+
```erb
|
|
213
|
+
<%= honeypot_field("user[website]") %>
|
|
214
|
+
<%= honeypot_signals %>
|
|
192
215
|
```
|
|
193
216
|
|
|
217
|
+
Guard the receiving action with the `honeypot` class macro:
|
|
218
|
+
|
|
194
219
|
```ruby
|
|
195
|
-
# app/controllers/sign_ups_controller.rb
|
|
196
220
|
class SignUpsController < ApplicationController
|
|
197
|
-
|
|
221
|
+
honeypot :website, wait: 2, only: :create
|
|
198
222
|
|
|
199
223
|
def create
|
|
200
224
|
# ...
|
|
201
225
|
end
|
|
226
|
+
end
|
|
227
|
+
```
|
|
202
228
|
|
|
203
|
-
|
|
229
|
+
When the honeypot is tripped, the request halts with `:no_content` by default.
|
|
230
|
+
To customize the response, pass a block:
|
|
204
231
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
)
|
|
232
|
+
```ruby
|
|
233
|
+
honeypot :website, only: :create do
|
|
234
|
+
redirect_to root_path, notice: "Moving on..."
|
|
235
|
+
end
|
|
236
|
+
```
|
|
211
237
|
|
|
212
|
-
|
|
213
|
-
|
|
238
|
+
To act on the input-signals rating inside the action:
|
|
239
|
+
|
|
240
|
+
```ruby
|
|
241
|
+
def create
|
|
242
|
+
rating = Otori.signals_rating(params)
|
|
243
|
+
# weight into your own scoring, or reject below a threshold
|
|
214
244
|
end
|
|
215
245
|
```
|
|
216
246
|
|
|
247
|
+
The adapter is a thin wrapper over the framework-agnostic core; if you prefer
|
|
248
|
+
to wire it up manually, `Otori.caught?` and `Otori.field` still work fine
|
|
249
|
+
inside a `before_action` and a helper method.
|
|
250
|
+
|
|
217
251
|
## Configuration
|
|
218
252
|
|
|
219
253
|
```ruby
|
data/lib/otori/rails.rb
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../otori"
|
|
4
|
+
|
|
5
|
+
module Otori
|
|
6
|
+
module Rails
|
|
7
|
+
module ControllerMacros
|
|
8
|
+
def honeypot(name, wait: nil, only: nil, except: nil, &on_caught)
|
|
9
|
+
filter_options = {}
|
|
10
|
+
filter_options[:only] = only if only
|
|
11
|
+
filter_options[:except] = except if except
|
|
12
|
+
|
|
13
|
+
before_action(**filter_options) do
|
|
14
|
+
next unless Otori.caught?(
|
|
15
|
+
name,
|
|
16
|
+
params:,
|
|
17
|
+
session:,
|
|
18
|
+
wait:
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
if on_caught
|
|
22
|
+
instance_exec(&on_caught)
|
|
23
|
+
else
|
|
24
|
+
head :no_content
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module Helpers
|
|
31
|
+
def honeypot_field(name, **attrs)
|
|
32
|
+
Otori.field(name, session: session, **attrs).html_safe
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def honeypot_signals(**attrs)
|
|
36
|
+
Otori.signals_field(**attrs).html_safe
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if defined?(::Rails::Railtie)
|
|
41
|
+
class Railtie < ::Rails::Railtie
|
|
42
|
+
initializer "otori.action_controller" do
|
|
43
|
+
ActiveSupport.on_load(:action_controller) do
|
|
44
|
+
extend Otori::Rails::ControllerMacros
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
initializer "otori.action_view" do
|
|
49
|
+
ActiveSupport.on_load(:action_view) do
|
|
50
|
+
include Otori::Rails::Helpers
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/otori/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: otori
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Wout
|
|
@@ -29,6 +29,7 @@ files:
|
|
|
29
29
|
- lib/otori/error.rb
|
|
30
30
|
- lib/otori/form.rb
|
|
31
31
|
- lib/otori/hanami.rb
|
|
32
|
+
- lib/otori/rails.rb
|
|
32
33
|
- lib/otori/signals.rb
|
|
33
34
|
- lib/otori/validator.rb
|
|
34
35
|
- lib/otori/version.rb
|
|
@@ -54,7 +55,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
54
55
|
- !ruby/object:Gem::Version
|
|
55
56
|
version: '0'
|
|
56
57
|
requirements: []
|
|
57
|
-
rubygems_version: 4.0.
|
|
58
|
+
rubygems_version: 4.0.19
|
|
58
59
|
specification_version: 4
|
|
59
60
|
summary: Invisible honeypot spam protection for Rack apps, with a Hanami adapter.
|
|
60
61
|
test_files: []
|