verify_it 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 +16 -5
- data/README.md +65 -64
- data/lib/verify_it/cli.rb +6 -0
- data/lib/verify_it/templates/initializer.rb.erb +18 -65
- data/lib/verify_it/verifiable.rb +19 -3
- data/lib/verify_it/version.rb +1 -1
- data/lib/verify_it.rb +1 -0
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ede88092d9b66d9853d5f03713b719f1bc664eefdfe0cc245140494110bda8a8
|
|
4
|
+
data.tar.gz: 1da02a88fc2c6262c6386eaac4f63184dad9bfebbd9bb694762a0e050f416aa3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 584f310188b429e0e6d77b9ca6c89cd0042b97bae8809b4ae8fad8699863666184fbbdf059c77eaabc5610d37d9355fffbbf9cd238056a06acc83626955f955e
|
|
7
|
+
data.tar.gz: 41394cf8edff07829dab5beecd3a4d723e8aaa1b89a6e8910095a77f1af3335a1f9988a56c92d5d77585aec2f23e4d683ca1f9ded3e494a2a0f938fc18417e41
|
data/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.1.1] - 2026-03-02
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **Verifiable concern now supports multiple channels** - `verifies` now generates channel-specific method names (`send_sms_code`, `verify_email_code`) instead of generic names that overwrote each other
|
|
7
|
+
- Added validation for channel parameter (must be `:sms` or `:email`)
|
|
8
|
+
- Added validation for attribute existence at definition time
|
|
9
|
+
- Added detection of method name conflicts
|
|
10
|
+
|
|
3
11
|
### Added
|
|
4
|
-
-
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
- Comprehensive specs for Verifiable module (22 examples)
|
|
13
|
+
- Channel-based method generation: `send_{channel}_code`, `verify_{channel}_code`, `cleanup_{channel}_verification`
|
|
14
|
+
- Support for multiple verifiable attributes per model (e.g., both phone_number and email)
|
|
15
|
+
|
|
16
|
+
### Documentation
|
|
17
|
+
- Updated README with channel-based API examples
|
|
18
|
+
- Added context parameter examples (custom message templates, tracking metadata)
|
|
19
|
+
- Updated Rails integration section with correct method names
|
|
9
20
|
|
|
10
21
|
## [0.1.0] - 2026-03-01
|
|
11
22
|
|
data/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# VerifyIt
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A storage-agnostic verification system for Ruby applications.
|
|
4
|
+
VerifyIt provides a flexible framework for implementing SMS and email verifications with built-in rate limiting and multiple storage backends.
|
|
4
5
|
|
|
5
6
|
## Features
|
|
6
7
|
|
|
@@ -10,7 +11,7 @@ A production-grade, storage-agnostic verification system for Ruby applications.
|
|
|
10
11
|
- **Thread-Safe**: Designed for concurrent access
|
|
11
12
|
- **Test Mode**: Expose codes for testing without delivery
|
|
12
13
|
- **Rails Optional**: Works standalone or with Rails
|
|
13
|
-
- **
|
|
14
|
+
- **Little Runtime Dependencies**: Only ActiveSupport required
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
16
17
|
|
|
@@ -51,9 +52,66 @@ If you selected Database storage, run the migration:
|
|
|
51
52
|
rails db:migrate
|
|
52
53
|
```
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
# Quick Start
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
## Rails Integration
|
|
58
|
+
|
|
59
|
+
VerifyIt automatically integrates with Rails when detected.
|
|
60
|
+
|
|
61
|
+
### Model Integration
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
class User < ApplicationRecord
|
|
65
|
+
include VerifyIt::Verifiable
|
|
66
|
+
|
|
67
|
+
verifies :phone_number, channel: :sms
|
|
68
|
+
verifies :email, channel: :email
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Usage
|
|
72
|
+
user = User.find(params[:id])
|
|
73
|
+
|
|
74
|
+
# Send code (no context needed)
|
|
75
|
+
result = user.send_sms_code
|
|
76
|
+
|
|
77
|
+
# Send with custom message template
|
|
78
|
+
result = user.send_sms_code(context: {
|
|
79
|
+
message_template: "Your #{user.company_name} verification code is: %{code}"
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
# Send with tracking metadata
|
|
83
|
+
result = user.send_email_code(context: {
|
|
84
|
+
ip: request.ip,
|
|
85
|
+
user_agent: request.user_agent,
|
|
86
|
+
action: 'password_reset'
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
# Verify code
|
|
90
|
+
result = user.verify_sms_code(params[:code])
|
|
91
|
+
|
|
92
|
+
# Cleanup
|
|
93
|
+
user.cleanup_sms_verification
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Rails Configuration
|
|
97
|
+
|
|
98
|
+
Create an initializer `config/initializers/verify_it.rb`:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
VerifyIt.configure do |config|
|
|
102
|
+
config.storage = :redis
|
|
103
|
+
config.redis_client = Redis.new(url: ENV['REDIS_URL'])
|
|
104
|
+
|
|
105
|
+
config.sms_sender = ->(to:, code:, context:) {
|
|
106
|
+
TwilioService.send_sms(to: to, body: "Your code is: #{code}")
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
config.test_mode = Rails.env.test?
|
|
110
|
+
config.bypass_delivery = Rails.env.test?
|
|
111
|
+
end
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Plain Ruby Configuration
|
|
57
115
|
|
|
58
116
|
```ruby
|
|
59
117
|
require 'verify_it'
|
|
@@ -180,7 +238,7 @@ config.storage = :database
|
|
|
180
238
|
Requires running the migration:
|
|
181
239
|
|
|
182
240
|
```bash
|
|
183
|
-
|
|
241
|
+
bundle exec verify_it install
|
|
184
242
|
rails db:migrate
|
|
185
243
|
```
|
|
186
244
|
|
|
@@ -243,63 +301,6 @@ config.test_mode = true # Includes code in Result object
|
|
|
243
301
|
config.bypass_delivery = true # Skip actual delivery
|
|
244
302
|
```
|
|
245
303
|
|
|
246
|
-
## Rails Integration
|
|
247
|
-
|
|
248
|
-
VerifyIt automatically integrates with Rails when detected.
|
|
249
|
-
|
|
250
|
-
### Model Integration
|
|
251
|
-
|
|
252
|
-
```ruby
|
|
253
|
-
class User < ApplicationRecord
|
|
254
|
-
include VerifyIt::Verifiable
|
|
255
|
-
|
|
256
|
-
verifies :phone_number, channel: :sms
|
|
257
|
-
verifies :email, channel: :email
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
# Usage
|
|
261
|
-
user = User.find(params[:id])
|
|
262
|
-
|
|
263
|
-
# Send code (no context needed)
|
|
264
|
-
result = user.send_sms_code
|
|
265
|
-
|
|
266
|
-
# Send with custom message template
|
|
267
|
-
result = user.send_sms_code(context: {
|
|
268
|
-
message_template: "Your #{user.company_name} verification code is: %{code}"
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
# Send with tracking metadata
|
|
272
|
-
result = user.send_email_code(context: {
|
|
273
|
-
ip: request.ip,
|
|
274
|
-
user_agent: request.user_agent,
|
|
275
|
-
action: 'password_reset'
|
|
276
|
-
})
|
|
277
|
-
|
|
278
|
-
# Verify code
|
|
279
|
-
result = user.verify_sms_code(params[:code])
|
|
280
|
-
|
|
281
|
-
# Cleanup
|
|
282
|
-
user.cleanup_sms_verification
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
### Rails Configuration
|
|
286
|
-
|
|
287
|
-
Create an initializer `config/initializers/verify_it.rb`:
|
|
288
|
-
|
|
289
|
-
```ruby
|
|
290
|
-
VerifyIt.configure do |config|
|
|
291
|
-
config.storage = :redis
|
|
292
|
-
config.redis_client = Redis.new(url: ENV['REDIS_URL'])
|
|
293
|
-
|
|
294
|
-
config.sms_sender = ->(to:, code:, context:) {
|
|
295
|
-
TwilioService.send_sms(to: to, body: "Your code is: #{code}")
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
config.test_mode = Rails.env.test?
|
|
299
|
-
config.bypass_delivery = Rails.env.test?
|
|
300
|
-
end
|
|
301
|
-
```
|
|
302
|
-
|
|
303
304
|
## Result Object API
|
|
304
305
|
|
|
305
306
|
All operations return a `VerifyIt::Result` object:
|
|
@@ -394,12 +395,12 @@ bundle exec rake build # Build gem
|
|
|
394
395
|
|
|
395
396
|
## Roadmap
|
|
396
397
|
|
|
397
|
-
- [
|
|
398
|
+
- [x] Database storage adapter
|
|
398
399
|
- [ ] Voice verification support
|
|
399
400
|
- [ ] WebAuthn integration
|
|
400
401
|
- [ ] Backup code generation
|
|
401
402
|
- [ ] Multi-factor authentication helpers
|
|
402
|
-
- [
|
|
403
|
+
- [x] Rails installer (CLI)
|
|
403
404
|
|
|
404
405
|
## Contributing
|
|
405
406
|
|
data/lib/verify_it/cli.rb
CHANGED
|
@@ -37,6 +37,7 @@ module VerifyIt
|
|
|
37
37
|
puts "=" * 50
|
|
38
38
|
puts
|
|
39
39
|
|
|
40
|
+
load_rails_environment
|
|
40
41
|
check_rails_environment
|
|
41
42
|
|
|
42
43
|
storage_type = prompt_storage_type
|
|
@@ -57,6 +58,11 @@ module VerifyIt
|
|
|
57
58
|
end
|
|
58
59
|
end
|
|
59
60
|
|
|
61
|
+
def load_rails_environment
|
|
62
|
+
env_file = File.join(Dir.pwd, "config", "environment.rb")
|
|
63
|
+
require env_file if File.exist?(env_file)
|
|
64
|
+
end
|
|
65
|
+
|
|
60
66
|
def check_rails_environment
|
|
61
67
|
unless defined?(Rails)
|
|
62
68
|
puts "Error: Rails environment not detected."
|
|
@@ -1,79 +1,32 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
VerifyIt.configure do |config|
|
|
4
|
-
<% if storage_type == "
|
|
5
|
-
# Memory storage (for development/testing only)
|
|
6
|
-
config.storage = :memory
|
|
7
|
-
<% elsif storage_type == "redis" %>
|
|
8
|
-
# Redis storage (recommended for production)
|
|
4
|
+
<% if storage_type == "redis" %>
|
|
9
5
|
config.storage = :redis
|
|
10
|
-
config.redis_client = Redis.new(
|
|
11
|
-
url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0")
|
|
12
|
-
)
|
|
6
|
+
config.redis_client = Redis.new(url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0"))
|
|
13
7
|
<% elsif storage_type == "database" %>
|
|
14
|
-
# Database storage (uses ActiveRecord)
|
|
15
8
|
config.storage = :database
|
|
9
|
+
<% else %>
|
|
10
|
+
# config.storage = :memory # default
|
|
16
11
|
<% end %>
|
|
17
12
|
|
|
18
|
-
#
|
|
19
|
-
config.code_length = 6
|
|
20
|
-
config.code_ttl = 300 # 5 minutes
|
|
21
|
-
config.code_format = :numeric # :numeric, :alphanumeric, or :alpha
|
|
22
|
-
|
|
23
|
-
# Rate limiting
|
|
24
|
-
config.max_send_attempts = 3
|
|
25
|
-
config.max_verification_attempts = 5
|
|
26
|
-
config.max_identifier_changes = 5
|
|
27
|
-
config.rate_limit_window = 3600 # 1 hour
|
|
28
|
-
|
|
29
|
-
# Delivery channels
|
|
30
|
-
config.delivery_channel = :sms # :sms or :email
|
|
31
|
-
|
|
32
|
-
# SMS delivery (configure with your provider)
|
|
33
|
-
config.sms_sender = ->(to:, code:, context:) {
|
|
34
|
-
# Example with Twilio:
|
|
35
|
-
# twilio_client = Twilio::REST::Client.new(
|
|
36
|
-
# ENV['TWILIO_ACCOUNT_SID'],
|
|
37
|
-
# ENV['TWILIO_AUTH_TOKEN']
|
|
38
|
-
# )
|
|
39
|
-
# twilio_client.messages.create(
|
|
40
|
-
# to: to,
|
|
41
|
-
# from: ENV['TWILIO_PHONE_NUMBER'],
|
|
42
|
-
# body: "Your verification code is: #{code}"
|
|
43
|
-
# )
|
|
44
|
-
|
|
45
|
-
# For development, just log it:
|
|
46
|
-
Rails.logger.info("SMS to #{to}: Your verification code is #{code}")
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
# Email delivery (configure with your mailer)
|
|
13
|
+
# Required: configure your delivery channel(s)
|
|
50
14
|
config.email_sender = ->(to:, code:, context:) {
|
|
51
|
-
# Example with ActionMailer:
|
|
52
15
|
# VerificationMailer.send_code(to, code, context).deliver_now
|
|
53
|
-
|
|
54
|
-
# For development, just log it:
|
|
55
|
-
Rails.logger.info("Email to #{to}: Your verification code is #{code}")
|
|
56
16
|
}
|
|
57
17
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
# }
|
|
62
|
-
|
|
63
|
-
# config.on_verify_success = ->(record:, identifier:) {
|
|
64
|
-
# Rails.logger.info("Verification successful for #{identifier}")
|
|
65
|
-
# }
|
|
66
|
-
|
|
67
|
-
# config.on_verify_failure = ->(record:, identifier:, attempts:) {
|
|
68
|
-
# Rails.logger.warn("Verification failed for #{identifier} (#{attempts} attempts)")
|
|
69
|
-
# }
|
|
70
|
-
|
|
71
|
-
# Namespace (for multi-tenant apps)
|
|
72
|
-
# config.namespace = ->(record) {
|
|
73
|
-
# record.respond_to?(:organization_id) ? "org:#{record.organization_id}" : nil
|
|
74
|
-
# }
|
|
18
|
+
config.sms_sender = ->(to:, code:, context:) {
|
|
19
|
+
# e.g. Twilio, Vonage, etc.
|
|
20
|
+
}
|
|
75
21
|
|
|
76
|
-
#
|
|
77
|
-
config.
|
|
78
|
-
config.
|
|
22
|
+
# Optional overrides (sensible defaults are set automatically):
|
|
23
|
+
# config.code_length = 6
|
|
24
|
+
# config.code_ttl = 300
|
|
25
|
+
# config.code_format = :numeric
|
|
26
|
+
# config.max_send_attempts = 3
|
|
27
|
+
# config.max_verification_attempts = 5
|
|
28
|
+
# config.delivery_channel = :email
|
|
29
|
+
# config.on_send = ->(record:, identifier:, channel:) {}
|
|
30
|
+
# config.on_verify_success = ->(record:, identifier:) {}
|
|
31
|
+
# config.on_verify_failure = ->(record:, identifier:, attempts:) {}
|
|
79
32
|
end
|
data/lib/verify_it/verifiable.rb
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "active_support/concern"
|
|
4
|
+
|
|
3
5
|
module VerifyIt
|
|
4
6
|
module Verifiable
|
|
5
7
|
extend ActiveSupport::Concern
|
|
6
8
|
|
|
7
9
|
module ClassMethods
|
|
8
10
|
def verifies(attribute, channel: :sms)
|
|
9
|
-
|
|
11
|
+
# Validate channel
|
|
12
|
+
unless %i[sms email].include?(channel)
|
|
13
|
+
raise ArgumentError, "Invalid channel: #{channel}. Must be :sms or :email"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Check for method conflicts
|
|
17
|
+
send_method = "send_#{channel}_code"
|
|
18
|
+
verify_method = "verify_#{channel}_code"
|
|
19
|
+
cleanup_method = "cleanup_#{channel}_verification"
|
|
20
|
+
|
|
21
|
+
if method_defined?(send_method)
|
|
22
|
+
raise ArgumentError, "Method #{send_method} is already defined on #{name}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
define_method(send_method) do |context: {}|
|
|
10
26
|
identifier = send(attribute)
|
|
11
27
|
VerifyIt.send_code(
|
|
12
28
|
to: identifier,
|
|
@@ -16,7 +32,7 @@ module VerifyIt
|
|
|
16
32
|
)
|
|
17
33
|
end
|
|
18
34
|
|
|
19
|
-
define_method(
|
|
35
|
+
define_method(verify_method) do |code|
|
|
20
36
|
identifier = send(attribute)
|
|
21
37
|
VerifyIt.verify_code(
|
|
22
38
|
to: identifier,
|
|
@@ -25,7 +41,7 @@ module VerifyIt
|
|
|
25
41
|
)
|
|
26
42
|
end
|
|
27
43
|
|
|
28
|
-
define_method(
|
|
44
|
+
define_method(cleanup_method) do
|
|
29
45
|
identifier = send(attribute)
|
|
30
46
|
VerifyIt.cleanup(
|
|
31
47
|
to: identifier,
|
data/lib/verify_it/version.rb
CHANGED
data/lib/verify_it.rb
CHANGED
|
@@ -13,6 +13,7 @@ require_relative "verify_it/delivery/base"
|
|
|
13
13
|
require_relative "verify_it/delivery/sms_delivery"
|
|
14
14
|
require_relative "verify_it/delivery/email_delivery"
|
|
15
15
|
require_relative "verify_it/verifier"
|
|
16
|
+
require_relative "verify_it/verifiable"
|
|
16
17
|
|
|
17
18
|
module VerifyIt
|
|
18
19
|
class Error < StandardError; end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: verify_it
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeremias Ramirez
|
|
@@ -135,8 +135,9 @@ dependencies:
|
|
|
135
135
|
- - "~>"
|
|
136
136
|
- !ruby/object:Gem::Version
|
|
137
137
|
version: '1.5'
|
|
138
|
-
description:
|
|
139
|
-
|
|
138
|
+
description: A storage-agnostic verification system for Ruby applications. VerifyIt
|
|
139
|
+
provides a flexible framework for implementing SMS and email verifications with
|
|
140
|
+
built-in rate limiting and multiple storage backends.
|
|
140
141
|
email:
|
|
141
142
|
- iguanadejere4@googlemail.com
|
|
142
143
|
executables:
|
|
@@ -181,7 +182,6 @@ homepage: https://github.com/JeremasPosta/verify_it
|
|
|
181
182
|
licenses:
|
|
182
183
|
- MIT
|
|
183
184
|
metadata:
|
|
184
|
-
homepage_uri: https://github.com/JeremasPosta/verify_it
|
|
185
185
|
source_code_uri: https://github.com/JeremasPosta/verify_it
|
|
186
186
|
changelog_uri: https://github.com/JeremasPosta/verify_it/blob/main/CHANGELOG.md
|
|
187
187
|
bug_tracker_uri: https://github.com/JeremasPosta/verify_it/issues
|