active_hashcash 0.1.1 → 0.2.0

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: 2a52910cc5af45ca4b31ce6af112ce45a4ec401e584d80076aa50247f9dfc154
4
- data.tar.gz: 03ca632ff343a29d9841cb950684c693b4d7684b1bd42251731fea8f8f1c36c8
3
+ metadata.gz: 81d808ca54efb58e16c61524bde0aee355f5a7b003ef4cb6cda2e9b672c7a284
4
+ data.tar.gz: 6ec6f99dd02e353bb4e86bb9db8e65ecf35dc46e13051e401b62608700b7fde5
5
5
  SHA512:
6
- metadata.gz: b2758deaf12537653c08a27a988aa18e13449975caaf73e854a39ad5011eca63430ac1eb019d9dc5bb66d415a0d8975a0908c833056d0422fdf8a1b192d3316e
7
- data.tar.gz: 579afe8ab7e448ffd550882fad8b4c8e724be3ec5ab043aac57c49463097a738cf66fd9700193d4f418a01f6ffb03d29510d5593b4800c659548abce968f81fc
6
+ metadata.gz: 17f8b181f15b009b850fea2e1ead3a5cb904218d8877b31d9b6a2e5f2578972a6a1a2837cdbda46013987911a88198d543dd7f3a79f68b455a969a005a3fbfc8
7
+ data.tar.gz: 2b02561bf0516b2accb42ac64fe8d93b7bf956bb9474fcadec93db08f4be551d9eea430884d133d08b92156a9d10440ac8f48067207c95d3b72e4268752748dd
data/CHANGELOG.md CHANGED
@@ -1,4 +1,6 @@
1
- ## [Unreleased]
1
+ ## 0.2.0 - 2022-08-02
2
+
3
+ - Add ActiveHashcash::Store#clean to removed expired stamps
2
4
 
3
5
  ## [0.1.1] - 2022-07-08
4
6
 
data/README.md CHANGED
@@ -66,6 +66,8 @@ You must have Redis in order to prevent double spent stamps. Otherwise it will b
66
66
  It automatically tries to connect with the environement variables `ACTIVE_HASHCASH_REDIS_URL` or `REDIS_URL`.
67
67
  You can also manually set the URL with `ActiveHashcash.redis_url = redis://user:password@localhost:6379`.
68
68
 
69
+ You should call `ActiveHashcash::Store#clean` once a day, to remove expired stamps.
70
+
69
71
  ## Complexity
70
72
 
71
73
  Complexity is the most important parameter. By default its value is 20 and requires most of the time 5 to 20 seconds to be solved on a decent laptop.
@@ -0,0 +1,19 @@
1
+ module ActiveHashcash
2
+ class Engine < ::Rails::Engine
3
+ config.assets.paths << File.expand_path("../..", __FILE__)
4
+
5
+ config.after_initialize { load_translations }
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
18
+ end
19
+ end
@@ -0,0 +1,52 @@
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
@@ -0,0 +1,25 @@
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
@@ -0,0 +1,3 @@
1
+ module ActiveHashcash
2
+ VERSION = "0.2.0"
3
+ end
@@ -9,14 +9,22 @@ module ActiveHashcash
9
9
 
10
10
  mattr_accessor :bits, instance_accessor: false, default: 20
11
11
  mattr_accessor :resource, instance_accessor: false
12
- mattr_accessor :redis_url, 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
+
18
+ def self.store=(store)
19
+ @store = store
20
+ end
13
21
 
14
22
  # TODO: protect_from_brute_force bits: 20, exception: ActionController::InvalidAuthenticityToken, with: :handle_failed_hashcash
15
23
 
16
24
  # Call me via a before_action when the form is submitted : `before_action :chech_hashcash, only: :create`
17
25
  def check_hashcash
18
- if hashcash_stamp_is_valid? && !hashcash_stamp_spent?
19
- hashcash_redis.sadd("active_hashcash_stamps".freeze, hashcash_param)
26
+ stamp = hashcash_param && Stamp.parse(hashcash_param)
27
+ if stamp && stamp.verify(hashcash_resource, hashcash_bits, Date.yesterday) && ActiveHashcash.store.add?(stamp)
20
28
  hashcash_after_success
21
29
  else
22
30
  hashcash_after_failure
@@ -63,88 +71,8 @@ module ActiveHashcash
63
71
  options = {resource: hashcash_resource, bits: hashcash_bits, waiting_message: hashcash_waiting_message}
64
72
  hidden_field_tag(name, "", "data-hashcash" => options.to_json)
65
73
  end
66
-
67
- def hashcash_redis
68
- @hashcash_redis = Redis.new(url: hashcash_redis_url)
69
- end
70
-
71
- def hashcash_redis_url
72
- ActiveHashcash.redis_url || ENV["ACTIVE_HASHCASH_REDIS_URL"] || ENV["REDIS_URL"]
73
- end
74
-
75
- def hashcash_stamp_is_valid?
76
- stamp = hashcash_param && Stamp.parse(hashcash_param)
77
- stamp && stamp.valid? && stamp.bits >= hashcash_bits && stamp.parse_date >= Date.yesterday
78
- end
79
-
80
- def hashcash_stamp_spent?
81
- hashcash_redis.sismember("active_hashcash_stamps".freeze, hashcash_param)
82
- end
83
-
84
-
85
-
86
- class Engine < ::Rails::Engine
87
- config.assets.paths << File.expand_path("..", __FILE__)
88
-
89
- config.after_initialize { load_translations }
90
-
91
- def load_translations
92
- if !I18n.backend.exists?(I18n.locale, "active_hashcash")
93
- I18n.backend.store_translations(:de, {active_hashcash: {waiting_label: "Warten auf die Überprüfung ..."}})
94
- I18n.backend.store_translations(:en, {active_hashcash: {waiting_label: "Waiting for verification ..."}})
95
- I18n.backend.store_translations(:es, {active_hashcash: {waiting_label: "A la espera de la verificación ..."}})
96
- I18n.backend.store_translations(:fr, {active_hashcash: {waiting_label: "En attente de vérification ..."}})
97
- I18n.backend.store_translations(:it, {active_hashcash: {waiting_label: "In attesa di verifica ..."}})
98
- I18n.backend.store_translations(:jp, {active_hashcash: {waiting_label: "検証待ち ..."}})
99
- I18n.backend.store_translations(:pt, {active_hashcash: {waiting_label: "À espera de verificação ..."}})
100
- end
101
- end
102
- end
103
-
104
- class Stamp
105
- attr_reader :version, :bits, :date, :resource, :extension, :rand, :counter
106
-
107
- def self.parse(string)
108
- args = string.split(":")
109
- new(args[0], args[1], args[2], args[3], args[4], args[5], args[6])
110
- end
111
-
112
- def self.mint(resource, options = {})
113
- new(
114
- options[:version] || 1,
115
- options[:bits] || ActiveHashcash.bits,
116
- options[:date] || Date.today.strftime("%y%m%d"),
117
- resource,
118
- options[:ext],
119
- options[:rand] || SecureRandom.alphanumeric(16),
120
- options[:counter] || 0).work
121
- end
122
-
123
- def initialize(version, bits, date, resource, extension, rand, counter)
124
- @version = version
125
- @bits = bits.to_i
126
- @date = date.respond_to?(:strftime) ? date.strftime("%y%m%d") : date
127
- @resource = resource
128
- @extension = extension
129
- @rand = rand
130
- @counter = counter
131
- end
132
-
133
- def valid?
134
- Digest::SHA1.hexdigest(to_s).hex >> (160-bits) == 0
135
- end
136
-
137
- def to_s
138
- [version, bits, date, resource, extension, rand, counter].join(":")
139
- end
140
-
141
- def parse_date
142
- Date.strptime(date, "%y%m%d")
143
- end
144
-
145
- def work
146
- @counter += 1 until valid?
147
- self
148
- end
149
- end
150
74
  end
75
+
76
+ require "active_hashcash/stamp"
77
+ require "active_hashcash/store"
78
+ require "active_hashcash/engine"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_hashcash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexis Bernard
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-07-08 00:00:00.000000000 Z
11
+ date: 2022-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -50,6 +50,10 @@ files:
50
50
  - LICENSE.txt
51
51
  - README.md
52
52
  - lib/active_hashcash.rb
53
+ - lib/active_hashcash/engine.rb
54
+ - lib/active_hashcash/stamp.rb
55
+ - lib/active_hashcash/store.rb
56
+ - lib/active_hashcash/version.rb
53
57
  - lib/hashcash.js
54
58
  homepage: https://github.com/BaseSecrete/active_hashcash
55
59
  licenses: