veri 0.2.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0782d4bd585ca9ca0aaa91cb51fe4b240d9e97ccf829c69890bc2079b38dda18'
4
- data.tar.gz: 56cd6f6147a7b23ea2a5cc0b12dd9d573fcae55dcbf49462f93a4db59d5ef724
3
+ metadata.gz: 6119b194fd813a1aad85a20b8513a15fe30143f601e1f2ce6cefa5d46085af70
4
+ data.tar.gz: c05d56946b5a010977bee885a807f2986e6d811eb3e9cc96cc0cc44ffe98b9f2
5
5
  SHA512:
6
- metadata.gz: 29763c6104a41dd4987ff30d4c75089d8390d5c36afb7d9f9f297fe627380f0b674d46d4c52aedb27865776d6915bd38ca4acacc2adda7894fe66d9e457bfeec
7
- data.tar.gz: '038ae16e36b31d87b4b83f7d51f51bb4c9d9318e6c161c9249f6eeff0a6a970343a2b1acbcb256edb4622bd03e01d1b6dda5c90c441274ef3b841f792dbc8ba6'
6
+ metadata.gz: eb7c6dfd8fe97b4c7a29b11cb06d01f29dc1ee86cf962512a6db239fcc2f3be1f0ebabc9875c4122843970daab8250d75cde8f4c63016f4580cae1169a41c3c7
7
+ data.tar.gz: a96429440653c18be22e9f425ef3dac167fc773666b0f99fb1ab0a08df747c8f27aa4f7d812d76f420a2974a48b46b916a14795f0445307dd0d73cc0f21e2f8b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## v0.2.1
2
+
3
+ ### Misc
4
+
5
+ - Enhanced error messages
6
+ - Performance improvements and code optimizations
7
+
1
8
  ## v0.2.0
2
9
 
3
10
  ### Breaking
@@ -10,31 +10,66 @@ module Veri
10
10
  setting :hashing_algorithm,
11
11
  default: :argon2,
12
12
  reader: true,
13
- constructor: -> (value) { Veri::Inputs.process(value, as: :hashing_algorithm, error: Veri::ConfigurationError) }
13
+ constructor: -> (value) do
14
+ Veri::Inputs.process(
15
+ value,
16
+ as: :hashing_algorithm,
17
+ error: Veri::ConfigurationError,
18
+ message: "Invalid hashing algorithm `#{value.inspect}`, supported algorithms are: #{Veri::Configuration::HASHERS.keys.join(", ")}"
19
+ )
20
+ end
14
21
  setting :inactive_session_lifetime,
15
22
  default: nil,
16
23
  reader: true,
17
- constructor: -> (value) { Veri::Inputs.process(value, as: :duration, optional: true, error: Veri::ConfigurationError) }
24
+ constructor: -> (value) do
25
+ Veri::Inputs.process(
26
+ value,
27
+ as: :duration,
28
+ optional: true,
29
+ error: Veri::ConfigurationError,
30
+ message: "Invalid inactive session lifetime `#{value.inspect}`, expected an instance of ActiveSupport::Duration or nil"
31
+ )
32
+ end
18
33
  setting :total_session_lifetime,
19
34
  default: 14.days,
20
35
  reader: true,
21
- constructor: -> (value) { Veri::Inputs.process(value, as: :duration, error: Veri::ConfigurationError) }
36
+ constructor: -> (value) do
37
+ Veri::Inputs.process(
38
+ value,
39
+ as: :duration,
40
+ error: Veri::ConfigurationError,
41
+ message: "Invalid total session lifetime `#{value.inspect}`, expected an instance of ActiveSupport::Duration"
42
+ )
43
+ end
22
44
  setting :user_model_name,
23
45
  default: "User",
24
46
  reader: true,
25
- constructor: -> (value) { Veri::Inputs.process(value, as: :string, error: Veri::ConfigurationError) }
47
+ constructor: -> (value) do
48
+ Veri::Inputs.process(
49
+ value,
50
+ as: :non_empty_string,
51
+ error: Veri::ConfigurationError,
52
+ message: "Invalid user model name `#{value.inspect}`, expected an ActiveRecord model name as a string"
53
+ )
54
+ end
55
+
56
+ HASHERS = {
57
+ argon2: Veri::Password::Argon2,
58
+ bcrypt: Veri::Password::BCrypt,
59
+ scrypt: Veri::Password::SCrypt
60
+ }.freeze
26
61
 
27
62
  def hasher
28
- case hashing_algorithm
29
- when :argon2 then Veri::Password::Argon2
30
- when :bcrypt then Veri::Password::BCrypt
31
- when :scrypt then Veri::Password::SCrypt
32
- else raise Veri::Error, "Invalid hashing algorithm: #{hashing_algorithm}"
33
- end
63
+ HASHERS.fetch(hashing_algorithm) { raise Veri::Error, "Invalid hashing algorithm: #{hashing_algorithm}" }
34
64
  end
35
65
 
36
66
  def user_model
37
- Veri::Inputs.process(user_model_name, as: :model, error: Veri::ConfigurationError)
67
+ Veri::Inputs.process(
68
+ user_model_name,
69
+ as: :model,
70
+ error: Veri::ConfigurationError,
71
+ message: "Invalid user model name `#{user_model_name}`, expected an ActiveRecord model name as a string"
72
+ )
38
73
  end
39
74
  end
40
75
  end
@@ -32,7 +32,12 @@ module Veri
32
32
  end
33
33
 
34
34
  def log_in(authenticatable)
35
- token = Veri::Session.establish(Veri::Inputs.process(authenticatable, as: :authenticatable), request)
35
+ processed_authenticatable = Veri::Inputs.process(
36
+ authenticatable,
37
+ as: :authenticatable,
38
+ message: "Expected an instance of #{Veri::Configuration.user_model_name}, got `#{authenticatable.inspect}`"
39
+ )
40
+ token = Veri::Session.establish(processed_authenticatable, request)
36
41
  cookies.encrypted.permanent[:veri_token] = { value: token, httponly: true }
37
42
  end
38
43
 
data/lib/veri/inputs.rb CHANGED
@@ -6,22 +6,26 @@ module Veri
6
6
 
7
7
  include Dry.Types()
8
8
 
9
- def process(value, as:, optional: false, error: Veri::InvalidArgumentError)
10
- checker = send(as)
9
+ TYPES = {
10
+ hashing_algorithm: -> { self::Strict::Symbol.enum(:argon2, :bcrypt, :scrypt) },
11
+ duration: -> { self::Instance(ActiveSupport::Duration) },
12
+ non_empty_string: -> { self::Strict::String.constrained(min_size: 1) },
13
+ model: -> { self::Strict::Class.constructor { _1.try(:safe_constantize) || _1 }.constrained(lt: ActiveRecord::Base) },
14
+ authenticatable: -> { self::Instance(Veri::Configuration.user_model) },
15
+ request: -> { self::Instance(ActionDispatch::Request) }
16
+ }.freeze
17
+
18
+ def process(value, as:, optional: false, error: Veri::InvalidArgumentError, message: nil)
19
+ checker = type_for(as)
11
20
  checker = checker.optional if optional
12
21
 
13
22
  checker[value]
14
23
  rescue Dry::Types::CoercionError => e
15
- raise error, e.message
24
+ raise error, message || e.message
16
25
  end
17
26
 
18
27
  private
19
28
 
20
- def hashing_algorithm = self::Strict::Symbol.enum(:argon2, :bcrypt, :scrypt)
21
- def duration = self::Instance(ActiveSupport::Duration)
22
- def string = self::Strict::String
23
- def model = self::Strict::Class.constructor { _1.try(:safe_constantize) || _1 }.constrained(lt: ActiveRecord::Base)
24
- def authenticatable = self::Instance(Veri::Configuration.user_model)
25
- def request = self::Instance(ActionDispatch::Request)
29
+ def type_for(name) = Veri::Inputs::TYPES.fetch(name).call
26
30
  end
27
31
  end
@@ -12,17 +12,32 @@ module Veri
12
12
 
13
13
  def update_password(password)
14
14
  update!(
15
- hashed_password: hasher.create(Veri::Inputs.process(password, as: :string)),
15
+ hashed_password: hasher.create(
16
+ Veri::Inputs.process(
17
+ password,
18
+ as: :non_empty_string,
19
+ message: "Expected a non-empty string, got `#{password.inspect}`"
20
+ )
21
+ ),
16
22
  password_updated_at: Time.current
17
23
  )
18
24
  end
19
25
 
20
26
  def verify_password(password)
21
- hasher.verify(Veri::Inputs.process(password, as: :string), hashed_password)
27
+ hasher.verify(
28
+ Veri::Inputs.process(
29
+ password,
30
+ as: :non_empty_string,
31
+ message: "Expected a non-empty string, got `#{password.inspect}`"
32
+ ),
33
+ hashed_password
34
+ )
22
35
  end
23
36
 
24
37
  private
25
38
 
26
- def hasher = Veri::Configuration.hasher
39
+ def hasher
40
+ @hasher ||= Veri::Configuration.hasher
41
+ end
27
42
  end
28
43
  end
@@ -55,7 +55,11 @@ module Veri
55
55
  update!(
56
56
  shapeshifted_at: Time.current,
57
57
  original_authenticatable: authenticatable,
58
- authenticatable: Veri::Inputs.process(user, as: :authenticatable)
58
+ authenticatable: Veri::Inputs.process(
59
+ user,
60
+ as: :authenticatable,
61
+ message: "Expected an instance of #{Veri::Configuration.user_model_name}, got `#{user.inspect}`"
62
+ )
59
63
  )
60
64
  end
61
65
 
@@ -68,14 +72,14 @@ module Veri
68
72
  end
69
73
 
70
74
  class << self
71
- def establish(authenticatable, request)
75
+ def establish(user, request)
72
76
  token = SecureRandom.hex(32)
73
77
  expires_at = Time.current + Veri::Configuration.total_session_lifetime
74
78
 
75
79
  new(
76
80
  hashed_token: Digest::SHA256.hexdigest(token),
77
81
  expires_at:,
78
- authenticatable: Veri::Inputs.process(authenticatable, as: :authenticatable, error: Veri::Error)
82
+ authenticatable: Veri::Inputs.process(user, as: :authenticatable, error: Veri::Error)
79
83
  ).update_info(
80
84
  Veri::Inputs.process(request, as: :request, error: Veri::Error)
81
85
  )
@@ -83,20 +87,36 @@ module Veri
83
87
  token
84
88
  end
85
89
 
86
- def prune(authenticatable = nil)
87
- processed_authenticatable = Veri::Inputs.process(authenticatable, as: :authenticatable, optional: true)
88
- scope = processed_authenticatable ? where(authenticatable: processed_authenticatable) : all
89
- to_be_pruned = scope.where(expires_at: ...Time.current)
90
+ def prune(user = nil)
91
+ scope = if user
92
+ where(
93
+ authenticatable: Veri::Inputs.process(
94
+ user,
95
+ as: :authenticatable,
96
+ optional: true,
97
+ message: "Expected an instance of #{Veri::Configuration.user_model_name} or nil, got `#{user.inspect}`"
98
+ )
99
+ )
100
+ else
101
+ all
102
+ end
103
+
104
+ expired_scope = scope.where(expires_at: ...Time.current)
105
+
90
106
  if Veri::Configuration.inactive_session_lifetime
91
- to_be_pruned = to_be_pruned.or(
92
- scope.where(last_seen_at: ...(Time.current - Veri::Configuration.inactive_session_lifetime))
93
- )
107
+ inactive_cutoff = Time.current - Veri::Configuration.inactive_session_lifetime
108
+ expired_scope = expired_scope.or(scope.where(last_seen_at: ...inactive_cutoff))
94
109
  end
95
- to_be_pruned.delete_all
110
+
111
+ expired_scope.delete_all
96
112
  end
97
113
 
98
- def terminate_all(authenticatable)
99
- Veri::Inputs.process(authenticatable, as: :authenticatable).veri_sessions.delete_all
114
+ def terminate_all(user)
115
+ Veri::Inputs.process(
116
+ user,
117
+ as: :authenticatable,
118
+ message: "Expected an instance of #{Veri::Configuration.user_model_name}, got `#{user.inspect}`"
119
+ ).veri_sessions.delete_all
100
120
  end
101
121
  end
102
122
  end
data/lib/veri/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Veri
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: veri
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - enjaku4