active_hashcash 0.2.0 → 0.3.1
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 +101 -14
- data/app/assets/config/active_hashcash_manifest.js +1 -0
- data/app/assets/javascripts/hashcash.js +257 -0
- data/app/assets/stylesheets/active_hashcash/application.css +15 -0
- data/app/controllers/active_hashcash/addresses_controller.rb +7 -0
- data/app/controllers/active_hashcash/application_controller.rb +4 -0
- data/app/controllers/active_hashcash/assets_controller.rb +34 -0
- data/app/controllers/active_hashcash/stamps_controller.rb +11 -0
- data/app/helpers/active_hashcash/addresses_helper.rb +4 -0
- data/app/helpers/active_hashcash/application_helper.rb +4 -0
- data/app/helpers/active_hashcash/stamps_helper.rb +4 -0
- data/app/jobs/active_hashcash/application_job.rb +4 -0
- data/app/mailers/active_hashcash/application_mailer.rb +6 -0
- data/app/models/active_hashcash/application_record.rb +5 -0
- data/app/models/active_hashcash/stamp.rb +70 -0
- data/app/views/active_hashcash/addresses/index.html.erb +17 -0
- data/app/views/active_hashcash/assets/_logo.svg.erb +1 -0
- data/app/views/active_hashcash/assets/_style.css +148 -0
- data/app/views/active_hashcash/assets/application.css.erb +1 -0
- data/app/views/active_hashcash/assets/ariato.css.erb +2 -0
- data/app/views/active_hashcash/assets/favicon.ico +0 -0
- data/app/views/active_hashcash/assets/favicon.svg.erb +1 -0
- data/app/views/active_hashcash/assets/vendor/_ariato_base.css +1297 -0
- data/app/views/active_hashcash/assets/vendor/_ariato_extra.css +1206 -0
- data/app/views/active_hashcash/stamps/_filters.html.erb +39 -0
- data/app/views/active_hashcash/stamps/index.html.erb +25 -0
- data/app/views/active_hashcash/stamps/show.html.erb +21 -0
- data/app/views/layouts/active_hashcash/application.html.erb +36 -0
- data/config/locales/de.yml +4 -0
- data/config/locales/en.yml +4 -0
- data/config/locales/es.yml +4 -0
- data/config/locales/fr.yml +4 -0
- data/config/locales/it.yml +4 -0
- data/config/locales/jp.yml +4 -0
- data/config/locales/pt.yml +4 -0
- data/config/routes.rb +6 -0
- data/db/migrate/20240215143453_create_active_hashcash_stamps.rb +25 -0
- data/lib/active_hashcash/engine.rb +2 -14
- data/lib/active_hashcash/version.rb +1 -1
- data/lib/active_hashcash.rb +35 -21
- data/lib/tasks/active_hashcash_tasks.rake +4 -0
- metadata +47 -26
- data/lib/active_hashcash/stamp.rb +0 -52
- data/lib/active_hashcash/store.rb +0 -25
@@ -0,0 +1,39 @@
|
|
1
|
+
<%= form_tag nil, method: :get do %>
|
2
|
+
<div class="grid-auto">
|
3
|
+
<div role="group">
|
4
|
+
<%= label_tag :created_from do %>
|
5
|
+
<%= ActiveHashcash::Stamp::human_attribute_name(:created_at) + " ≥" %>
|
6
|
+
<%= date_field_tag :created_from, params[:created_from] %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<%= label_tag :created_from do %>
|
10
|
+
<%= ActiveHashcash::Stamp::human_attribute_name(:created_at) + " ≤" %>
|
11
|
+
<%= date_field_tag :created_to, params[:created_to] %>
|
12
|
+
<% end %>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div role="group">
|
16
|
+
<%= label_tag :bits_from do %>
|
17
|
+
<%= ActiveHashcash::Stamp::human_attribute_name(:bits) + " ≥" %>
|
18
|
+
<%= number_field_tag :bits_from, params[:bits_from] %>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<%= label_tag :bits_to do %>
|
22
|
+
<%= ActiveHashcash::Stamp::human_attribute_name(:bits) + " ≤" %>
|
23
|
+
<%= number_field_tag :bits_to, params[:bits_to] %>
|
24
|
+
<% end %>
|
25
|
+
</div>
|
26
|
+
|
27
|
+
<div>
|
28
|
+
<%= label_tag :ip_address_starts_with, ActiveHashcash::Stamp::human_attribute_name(:ip_address) %>
|
29
|
+
<%= text_field_tag :ip_address_starts_with, params[:ip_address_starts_with] %>
|
30
|
+
</div>
|
31
|
+
|
32
|
+
<div>
|
33
|
+
<%= label_tag :request_path_starts_with, ActiveHashcash::Stamp::human_attribute_name(:request_path) %>
|
34
|
+
<%= text_field_tag :request_path_starts_with, params[:request_path_starts_with] %>
|
35
|
+
</div>
|
36
|
+
|
37
|
+
<%= submit_tag t("active_hashcash.submit_filter") %>
|
38
|
+
</div>
|
39
|
+
<% end %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<details>
|
2
|
+
<summary>Filters</summary>
|
3
|
+
<%= render "filters" %>
|
4
|
+
</details>
|
5
|
+
|
6
|
+
<table>
|
7
|
+
<thead>
|
8
|
+
<tr>
|
9
|
+
<th><%= ActiveHashcash::Stamp.human_attribute_name(:created_at) %></th>
|
10
|
+
<th><%= ActiveHashcash::Stamp.human_attribute_name(:ip_address) %></th>
|
11
|
+
<th><%= ActiveHashcash::Stamp.human_attribute_name(:request_path) %></th>
|
12
|
+
<th><%= ActiveHashcash::Stamp.human_attribute_name(:bits) %></th>
|
13
|
+
</tr>
|
14
|
+
</thead>
|
15
|
+
<tbody>
|
16
|
+
<% for stamp in @stamps %>
|
17
|
+
<tr>
|
18
|
+
<td><%= link_to stamp.created_at, stamp %></td>
|
19
|
+
<td><%= stamp.ip_address %></td>
|
20
|
+
<td><%= stamp.request_path %></td>
|
21
|
+
<td><%= stamp.bits %></td>
|
22
|
+
</tr>
|
23
|
+
<% end %>
|
24
|
+
</tbody>
|
25
|
+
</table>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
<h3><%= @stamp %></h3>
|
3
|
+
<dl>
|
4
|
+
<dt><%= @stamp.class.human_attribute_name(:created_at) %></dt>
|
5
|
+
<dd><%= l @stamp.created_at %></dd>
|
6
|
+
|
7
|
+
<dt><%= @stamp.class.human_attribute_name(:resource) %></dt>
|
8
|
+
<dd><%= @stamp.resource %></dd>
|
9
|
+
|
10
|
+
<dt><%= @stamp.class.human_attribute_name(:bits) %></dt>
|
11
|
+
<dd><%= @stamp.bits %></dd>
|
12
|
+
|
13
|
+
<dt><%= @stamp.class.human_attribute_name(:ip_address) %></dt>
|
14
|
+
<dd><%= @stamp.ip_address %></dd>
|
15
|
+
|
16
|
+
<dt><%= @stamp.class.human_attribute_name(:request_path) %></dt>
|
17
|
+
<dd><%= @stamp.request_path %></dd>
|
18
|
+
|
19
|
+
<dt><%= @stamp.class.human_attribute_name(:context) %></dt>
|
20
|
+
<dd><%= @stamp.context %></dd>
|
21
|
+
</dl>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html class="active-analytics">
|
3
|
+
<head>
|
4
|
+
<title>Active Hashcash</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
<%= csp_meta_tag %>
|
7
|
+
|
8
|
+
<%= tag.link rel: "icon", href: asset_path(:favicon, format: :ico), sizes: "32x32" %>
|
9
|
+
<%= tag.link rel: "icon", href: asset_path(:favicon, format: :svg), type: "image/svg+xml" %>
|
10
|
+
|
11
|
+
<%= tag.link rel: "stylesheet", href: asset_path(:ariato, format: :css) %>
|
12
|
+
<%= tag.link rel: "stylesheet", href: asset_path(:application, format: :css) %>
|
13
|
+
</head>
|
14
|
+
<body>
|
15
|
+
<header>
|
16
|
+
<nav aria-label="site">
|
17
|
+
<ul role="menu" aria-label="Elements" class="is-horizontal">
|
18
|
+
<li role="none" class="logo"><%= link_to(root_path) { render partial: "/active_hashcash/assets/logo", formats: [:svg] } %></li>
|
19
|
+
<li role="none"><%= link_to_unless_current ActiveHashcash::Stamp.model_name.human.pluralize, stamps_path %></li>
|
20
|
+
<li role="none"><%= link_to_unless_current "Top IP addresses", addresses_path %></li>
|
21
|
+
</ul>
|
22
|
+
</nav>
|
23
|
+
</header>
|
24
|
+
|
25
|
+
<main class="card">
|
26
|
+
<%= yield %>
|
27
|
+
</main>
|
28
|
+
|
29
|
+
<footer>
|
30
|
+
Made by <a href="https://www.rorvswild.com">RorVsWild</a> |
|
31
|
+
<a href="https://github.com/BaseSecrete/active_hashcash">Source code</a> |
|
32
|
+
<a href="https://twitter.com/rorvswild">Twitter</a> |
|
33
|
+
<a href="https://ruby.social/@rorvswild">Mastodon</a> |
|
34
|
+
</footer>
|
35
|
+
</body>
|
36
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class CreateActiveHashcashStamps < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
create_table :active_hashcash_stamps do |t|
|
4
|
+
t.string :version, null: false
|
5
|
+
t.integer :bits, null: false
|
6
|
+
t.date :date, null: false
|
7
|
+
t.string :resource, null: false
|
8
|
+
t.string :ext, null: false
|
9
|
+
t.string :rand, null: false
|
10
|
+
t.string :counter, null: false
|
11
|
+
t.string :request_path
|
12
|
+
t.string :ip_address
|
13
|
+
|
14
|
+
if t.respond_to?(:jsonb)
|
15
|
+
t.jsonb :context # SQLite JSONB support from version 3.45 (2024-01-15)
|
16
|
+
elsif t.respond_to?(:json)
|
17
|
+
t.json :context
|
18
|
+
end
|
19
|
+
|
20
|
+
t.timestamps
|
21
|
+
end
|
22
|
+
add_index :active_hashcash_stamps, [:ip_address, :created_at], where: "ip_address IS NOT NULL"
|
23
|
+
add_index :active_hashcash_stamps, [:counter, :rand, :date, :resource, :bits, :version, :ext], name: "index_active_hashcash_stamps_unique", unique: true
|
24
|
+
end
|
25
|
+
end
|
@@ -1,19 +1,7 @@
|
|
1
1
|
module ActiveHashcash
|
2
2
|
class Engine < ::Rails::Engine
|
3
|
-
config.assets.paths << File.expand_path("../..", __FILE__)
|
3
|
+
config.assets.paths << File.expand_path("../..", __FILE__) if config.respond_to?(:assets)
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
def load_translations
|
8
|
-
if !I18n.backend.exists?(I18n.locale, "active_hashcash")
|
9
|
-
I18n.backend.store_translations(:de, {active_hashcash: {waiting_label: "Warten auf die Überprüfung ..."}})
|
10
|
-
I18n.backend.store_translations(:en, {active_hashcash: {waiting_label: "Waiting for verification ..."}})
|
11
|
-
I18n.backend.store_translations(:es, {active_hashcash: {waiting_label: "A la espera de la verificación ..."}})
|
12
|
-
I18n.backend.store_translations(:fr, {active_hashcash: {waiting_label: "En attente de vérification ..."}})
|
13
|
-
I18n.backend.store_translations(:it, {active_hashcash: {waiting_label: "In attesa di verifica ..."}})
|
14
|
-
I18n.backend.store_translations(:jp, {active_hashcash: {waiting_label: "検証待ち ..."}})
|
15
|
-
I18n.backend.store_translations(:pt, {active_hashcash: {waiting_label: "À espera de verificação ..."}})
|
16
|
-
end
|
17
|
-
end
|
5
|
+
isolate_namespace ActiveHashcash
|
18
6
|
end
|
19
7
|
end
|
data/lib/active_hashcash.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require "active_hashcash/version"
|
2
|
+
require "active_hashcash/engine"
|
3
|
+
|
1
4
|
module ActiveHashcash
|
2
5
|
extend ActiveSupport::Concern
|
3
6
|
|
@@ -7,31 +10,41 @@ module ActiveHashcash
|
|
7
10
|
helper_method :hashcash_hidden_field_tag
|
8
11
|
end
|
9
12
|
|
10
|
-
mattr_accessor :bits, instance_accessor: false, default: 20
|
11
13
|
mattr_accessor :resource, instance_accessor: false
|
12
|
-
mattr_accessor :redis_url, instance_accessor: false, default: ENV["ACTIVE_HASHCASH_REDIS_URL"] || ENV["REDIS_URL"]
|
13
|
-
|
14
|
-
def self.store
|
15
|
-
@store ||= Store.new(Redis.new(url: ActiveHashcash.redis_url))
|
16
|
-
end
|
17
14
|
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
# This is base complexity.
|
16
|
+
# Consider lowering it to not exclude people with old and slow devices.
|
17
|
+
mattr_accessor :bits, instance_accessor: false, default: 16
|
21
18
|
|
22
|
-
|
19
|
+
mattr_accessor :date_format, instance_accessor: false, default: "%y%m%d"
|
23
20
|
|
24
|
-
# Call me via a before_action when the form is submitted : `before_action :
|
21
|
+
# Call me via a before_action when the form is submitted : `before_action :check_hashcash, only: :create`
|
25
22
|
def check_hashcash
|
26
|
-
|
27
|
-
|
23
|
+
attrs = {
|
24
|
+
ip_address: hashcash_ip_address,
|
25
|
+
request_path: hashcash_request_path,
|
26
|
+
context: hashcash_stamp_context
|
27
|
+
}
|
28
|
+
if hashcash_param && Stamp.spend(hashcash_param, hashcash_resource, hashcash_bits, Date.yesterday, attrs)
|
28
29
|
hashcash_after_success
|
29
30
|
else
|
30
31
|
hashcash_after_failure
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
34
|
-
# Override the methods below in your controller, to change any parameter
|
35
|
+
# Override the methods below in your controller, to change any parameter or behaviour.
|
36
|
+
|
37
|
+
def hashcash_ip_address
|
38
|
+
request.remote_ip
|
39
|
+
end
|
40
|
+
|
41
|
+
def hashcash_request_path
|
42
|
+
request.path
|
43
|
+
end
|
44
|
+
|
45
|
+
def hashcash_stamp_context
|
46
|
+
# Override this method to store custom data for each stamp
|
47
|
+
end
|
35
48
|
|
36
49
|
# By default the host name is used as the resource.
|
37
50
|
# It' should be good for most cases and prevent from reusing the same stamp between sites.
|
@@ -39,10 +52,15 @@ module ActiveHashcash
|
|
39
52
|
ActiveHashcash.resource || request.host
|
40
53
|
end
|
41
54
|
|
42
|
-
#
|
43
|
-
#
|
55
|
+
# Returns the complexity, the higher the slower it is.
|
56
|
+
# Complexity is increased logarithmicly for each IP during the last 24H to slowdown brute force attacks.
|
57
|
+
# The minimun value returned is `ActiveHashcash.bits`.
|
44
58
|
def hashcash_bits
|
45
|
-
ActiveHashcash.
|
59
|
+
if (previous_stamp_count = ActiveHashcash::Stamp.where(ip_address: hashcash_ip_address).where(created_at: 1.day.ago..).count) > 0
|
60
|
+
(ActiveHashcash.bits + Math.log2(previous_stamp_count)).floor
|
61
|
+
else
|
62
|
+
ActiveHashcash.bits
|
63
|
+
end
|
46
64
|
end
|
47
65
|
|
48
66
|
# Override if you want to rename the hashcash param.
|
@@ -72,7 +90,3 @@ module ActiveHashcash
|
|
72
90
|
hidden_field_tag(name, "", "data-hashcash" => options.to_json)
|
73
91
|
end
|
74
92
|
end
|
75
|
-
|
76
|
-
require "active_hashcash/stamp"
|
77
|
-
require "active_hashcash/store"
|
78
|
-
require "active_hashcash/engine"
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_hashcash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexis Bernard
|
8
|
-
autorequire:
|
9
|
-
bindir:
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: redis
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 4.0.0
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 4.0.0
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: rails
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,8 +24,8 @@ dependencies:
|
|
38
24
|
- - ">="
|
39
25
|
- !ruby/object:Gem::Version
|
40
26
|
version: 5.2.0
|
41
|
-
description:
|
42
|
-
|
27
|
+
description: Protect Rails applications against bots and brute force attacks without
|
28
|
+
annoying humans.
|
43
29
|
email:
|
44
30
|
- alexis@basesecrete.com
|
45
31
|
executables: []
|
@@ -49,12 +35,47 @@ files:
|
|
49
35
|
- CHANGELOG.md
|
50
36
|
- LICENSE.txt
|
51
37
|
- README.md
|
38
|
+
- app/assets/config/active_hashcash_manifest.js
|
39
|
+
- app/assets/javascripts/hashcash.js
|
40
|
+
- app/assets/stylesheets/active_hashcash/application.css
|
41
|
+
- app/controllers/active_hashcash/addresses_controller.rb
|
42
|
+
- app/controllers/active_hashcash/application_controller.rb
|
43
|
+
- app/controllers/active_hashcash/assets_controller.rb
|
44
|
+
- app/controllers/active_hashcash/stamps_controller.rb
|
45
|
+
- app/helpers/active_hashcash/addresses_helper.rb
|
46
|
+
- app/helpers/active_hashcash/application_helper.rb
|
47
|
+
- app/helpers/active_hashcash/stamps_helper.rb
|
48
|
+
- app/jobs/active_hashcash/application_job.rb
|
49
|
+
- app/mailers/active_hashcash/application_mailer.rb
|
50
|
+
- app/models/active_hashcash/application_record.rb
|
51
|
+
- app/models/active_hashcash/stamp.rb
|
52
|
+
- app/views/active_hashcash/addresses/index.html.erb
|
53
|
+
- app/views/active_hashcash/assets/_logo.svg.erb
|
54
|
+
- app/views/active_hashcash/assets/_style.css
|
55
|
+
- app/views/active_hashcash/assets/application.css.erb
|
56
|
+
- app/views/active_hashcash/assets/ariato.css.erb
|
57
|
+
- app/views/active_hashcash/assets/favicon.ico
|
58
|
+
- app/views/active_hashcash/assets/favicon.svg.erb
|
59
|
+
- app/views/active_hashcash/assets/vendor/_ariato_base.css
|
60
|
+
- app/views/active_hashcash/assets/vendor/_ariato_extra.css
|
61
|
+
- app/views/active_hashcash/stamps/_filters.html.erb
|
62
|
+
- app/views/active_hashcash/stamps/index.html.erb
|
63
|
+
- app/views/active_hashcash/stamps/show.html.erb
|
64
|
+
- app/views/layouts/active_hashcash/application.html.erb
|
65
|
+
- config/locales/de.yml
|
66
|
+
- config/locales/en.yml
|
67
|
+
- config/locales/es.yml
|
68
|
+
- config/locales/fr.yml
|
69
|
+
- config/locales/it.yml
|
70
|
+
- config/locales/jp.yml
|
71
|
+
- config/locales/pt.yml
|
72
|
+
- config/routes.rb
|
73
|
+
- db/migrate/20240215143453_create_active_hashcash_stamps.rb
|
52
74
|
- lib/active_hashcash.rb
|
53
75
|
- lib/active_hashcash/engine.rb
|
54
|
-
- lib/active_hashcash/stamp.rb
|
55
|
-
- lib/active_hashcash/store.rb
|
56
76
|
- lib/active_hashcash/version.rb
|
57
77
|
- lib/hashcash.js
|
78
|
+
- lib/tasks/active_hashcash_tasks.rake
|
58
79
|
homepage: https://github.com/BaseSecrete/active_hashcash
|
59
80
|
licenses:
|
60
81
|
- MIT
|
@@ -62,7 +83,7 @@ metadata:
|
|
62
83
|
homepage_uri: https://github.com/BaseSecrete/active_hashcash
|
63
84
|
source_code_uri: https://github.com/BaseSecrete/active_hashcash
|
64
85
|
changelog_uri: https://github.com/BaseSecrete/active_hashcash/CHANGELOG.md
|
65
|
-
post_install_message:
|
86
|
+
post_install_message:
|
66
87
|
rdoc_options: []
|
67
88
|
require_paths:
|
68
89
|
- lib
|
@@ -78,8 +99,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
99
|
version: '0'
|
79
100
|
requirements: []
|
80
101
|
rubygems_version: 3.2.22
|
81
|
-
signing_key:
|
102
|
+
signing_key:
|
82
103
|
specification_version: 4
|
83
|
-
summary:
|
84
|
-
|
104
|
+
summary: Protect Rails applications against bots and brute force attacks without annoying
|
105
|
+
humans.
|
85
106
|
test_files: []
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module ActiveHashcash
|
2
|
-
class Stamp
|
3
|
-
attr_reader :version, :bits, :date, :resource, :extension, :rand, :counter
|
4
|
-
|
5
|
-
def self.parse(string)
|
6
|
-
args = string.split(":")
|
7
|
-
new(args[0], args[1], args[2], args[3], args[4], args[5], args[6])
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.mint(resource, options = {})
|
11
|
-
new(
|
12
|
-
options[:version] || 1,
|
13
|
-
options[:bits] || ActiveHashcash.bits,
|
14
|
-
options[:date] || Date.today.strftime("%y%m%d"),
|
15
|
-
resource,
|
16
|
-
options[:ext],
|
17
|
-
options[:rand] || SecureRandom.alphanumeric(16),
|
18
|
-
options[:counter] || 0).work
|
19
|
-
end
|
20
|
-
|
21
|
-
def initialize(version, bits, date, resource, extension, rand, counter)
|
22
|
-
@version = version
|
23
|
-
@bits = bits.to_i
|
24
|
-
@date = date.respond_to?(:strftime) ? date.strftime("%y%m%d") : date
|
25
|
-
@resource = resource
|
26
|
-
@extension = extension
|
27
|
-
@rand = rand
|
28
|
-
@counter = counter
|
29
|
-
end
|
30
|
-
|
31
|
-
def valid?
|
32
|
-
Digest::SHA1.hexdigest(to_s).hex >> (160-bits) == 0
|
33
|
-
end
|
34
|
-
|
35
|
-
def verify(resource, bits, date)
|
36
|
-
self.resource == resource && self.bits >= bits && parse_date >= date && valid?
|
37
|
-
end
|
38
|
-
|
39
|
-
def to_s
|
40
|
-
[version, bits, date, resource, extension, rand, counter].join(":")
|
41
|
-
end
|
42
|
-
|
43
|
-
def parse_date
|
44
|
-
Date.strptime(date, "%y%m%d")
|
45
|
-
end
|
46
|
-
|
47
|
-
def work
|
48
|
-
@counter += 1 until valid?
|
49
|
-
self
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module ActiveHashcash
|
2
|
-
class Store
|
3
|
-
attr_reader :redis
|
4
|
-
|
5
|
-
def initialize(redis = Redis.new(url: ActiveHashcash.redis_url || ENV["ACTIVE_HASHCASH_REDIS_URL"] || ENV["REDIS_URL"]))
|
6
|
-
@redis = redis
|
7
|
-
end
|
8
|
-
|
9
|
-
def add?(stamp)
|
10
|
-
redis.sadd("active_hashcash_stamps_#{stamp.date}", stamp) ? self : nil
|
11
|
-
end
|
12
|
-
|
13
|
-
def clear
|
14
|
-
redis.del(redis.keys("active_hashcash_stamps*"))
|
15
|
-
end
|
16
|
-
|
17
|
-
def clean
|
18
|
-
today = Date.today.strftime("%y%m%d")
|
19
|
-
yesterday = (Date.today - 1).strftime("%y%m%d")
|
20
|
-
keep = ["active_hashcash_stamps_#{today}", "active_hashcash_stamps_#{yesterday}"]
|
21
|
-
keys = redis.keys("active_hashcash_stamps*")
|
22
|
-
redis.del(keys - keep)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|