sequel_auth 0.0.6
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 +7 -0
- data/lib/providers/bcrypt.rb +35 -0
- data/lib/providers/crypt.rb +42 -0
- data/lib/providers/scrypt.rb +66 -0
- data/lib/sequel_auth.rb +92 -0
- data/lib/sequel_auth/version.rb +9 -0
- metadata +124 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7520438387075590996072d0bf3f39a4590313d5cd4ac9ebbd7bfe75b7a4c1c6
|
|
4
|
+
data.tar.gz: 9e9619c3be523a75011aa8469b4704f9572df4d6d566f8d7fb2463243e20cdd1
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: de9544a0e81aee9437200aa43f7a1dae108394a12e6a21a123fd4b95d450cbc8b878395318e96e608e53786cef005252547283ac386094d282219ec76b0ef781
|
|
7
|
+
data.tar.gz: 27b30df7effd4556194675dcd6d5e847a1dab66a7eb1565f37b5ae052dae47076ffd3eab6b2356cb294c58b41e9de63a1a9e59965b0c5f006a57e653aaa24f08
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require "bcrypt"
|
|
2
|
+
|
|
3
|
+
module SequelAuth
|
|
4
|
+
module Providers
|
|
5
|
+
class Bcrypt
|
|
6
|
+
class << self
|
|
7
|
+
|
|
8
|
+
def cost
|
|
9
|
+
@cost ||= ::BCrypt::Engine.cost
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def cost=(val)
|
|
13
|
+
raise ArgumentError,"cost < #{min_cost} not allowed!" if val < min_cost
|
|
14
|
+
@cost = val
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def encrypt(password)
|
|
18
|
+
raise ArgumentError, "password not a valid string" if !password.is_a?(String) || password.strip.empty?
|
|
19
|
+
::BCrypt::Password.create(password, cost: cost)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def matches?(hash,password)
|
|
23
|
+
::BCrypt::Password.new(hash)==password
|
|
24
|
+
rescue ::BCrypt::Errors::InvalidHash
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
def min_cost
|
|
30
|
+
::BCrypt::Engine::MIN_COST
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SequelAuth
|
|
4
|
+
module Providers
|
|
5
|
+
class Crypt
|
|
6
|
+
class << self
|
|
7
|
+
|
|
8
|
+
attr_writer :salt_prefix,:salt_size
|
|
9
|
+
# Salt prefix - prefix for random salt
|
|
10
|
+
def salt_prefix
|
|
11
|
+
@salt_prefix ||= defaults[:salt_prefix]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Salt size - size as number
|
|
15
|
+
def salt_size
|
|
16
|
+
@salt_size ||= defaults[:salt_size]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def salt
|
|
20
|
+
salt_prefix + (salt_size-salt_prefix.length).times.map {
|
|
21
|
+
(('a'..'z').to_a + (1..9).to_a + ('A'..'Z').to_a).sample
|
|
22
|
+
}.join
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def encrypt(password)
|
|
26
|
+
password.crypt(salt)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def matches?(hash, password)
|
|
30
|
+
password.crypt(hash) == hash
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def defaults
|
|
34
|
+
{
|
|
35
|
+
salt_prefix: "$6$",
|
|
36
|
+
salt_size: 16,
|
|
37
|
+
}.freeze
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "scrypt"
|
|
4
|
+
|
|
5
|
+
module SequelAuth
|
|
6
|
+
module Providers
|
|
7
|
+
class Scrypt
|
|
8
|
+
class << self
|
|
9
|
+
|
|
10
|
+
attr_writer :key_len, :salt_size, :max_time, :max_mem, :max_memfrac
|
|
11
|
+
# Key length - length in bytes of generated key, from 16 to 512.
|
|
12
|
+
def key_len
|
|
13
|
+
@key_len ||= defaults[:key_len]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Salt size - size in bytes of random salt, from 8 to 32
|
|
17
|
+
def salt_size
|
|
18
|
+
@salt_size ||= defaults[:salt_size]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Max time - maximum time spent in computation
|
|
22
|
+
def max_time
|
|
23
|
+
@max_time ||= defaults[:max_time]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Max memory - maximum memory usage. The minimum is always 1MB
|
|
27
|
+
def max_mem
|
|
28
|
+
@max_mem ||= defaults[:max_mem]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Max memory fraction - maximum memory out of all available. Always
|
|
32
|
+
# greater than zero and <= 0.5.
|
|
33
|
+
def max_memfrac
|
|
34
|
+
@max_memfrac ||= defaults[:max_memfrac]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def encrypt(password)
|
|
38
|
+
::SCrypt::Password.create(
|
|
39
|
+
password,
|
|
40
|
+
key_len: key_len,
|
|
41
|
+
salt_size: salt_size,
|
|
42
|
+
max_mem: max_mem,
|
|
43
|
+
max_memfrac: max_memfrac,
|
|
44
|
+
max_time: max_time
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def matches?(hash, password)
|
|
49
|
+
::SCrypt::Password.new(hash)==password
|
|
50
|
+
rescue ::SCrypt::Errors::InvalidHash
|
|
51
|
+
false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def defaults
|
|
55
|
+
{
|
|
56
|
+
key_len: 32,
|
|
57
|
+
salt_size: 8,
|
|
58
|
+
max_time: 0.2,
|
|
59
|
+
max_mem: 1024 * 1024,
|
|
60
|
+
max_memfrac: 0.5
|
|
61
|
+
}.freeze
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
data/lib/sequel_auth.rb
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require "sequel"
|
|
2
|
+
require "securerandom"
|
|
3
|
+
require_relative "providers/bcrypt"
|
|
4
|
+
require_relative "providers/scrypt"
|
|
5
|
+
require_relative "providers/crypt"
|
|
6
|
+
|
|
7
|
+
module Sequel
|
|
8
|
+
module Plugins
|
|
9
|
+
module SequelAuth
|
|
10
|
+
def self.provider(provider,opts={})
|
|
11
|
+
provider = Kernel.const_get("SequelAuth::Providers::#{provider.to_s.capitalize}")
|
|
12
|
+
opts.each { |k,v| provider.public_send("#{k}=", v) }
|
|
13
|
+
provider
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.configure(model, opts = {})
|
|
17
|
+
model.instance_eval do
|
|
18
|
+
@digest_column = opts.fetch(:digest_column, :password_digest)
|
|
19
|
+
@include_validations = opts.fetch(:include_validations, true)
|
|
20
|
+
@provider = SequelAuth.provider opts.fetch(:provider, :bcrypt),
|
|
21
|
+
opts.fetch(:provider_opts, {})
|
|
22
|
+
#Optional columns
|
|
23
|
+
@access_token_column = opts.fetch(:access_token_column, nil)
|
|
24
|
+
@login_count_column = opts.fetch(:login_count_column, nil)
|
|
25
|
+
@failed_login_count_column = opts.fetch(:failed_login_count_column, nil)
|
|
26
|
+
@last_login_at_column = opts.fetch(:last_login_at_column,nil)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module ClassMethods
|
|
31
|
+
attr_reader :provider,
|
|
32
|
+
:digest_column,
|
|
33
|
+
:access_token_column,
|
|
34
|
+
:login_count_column,
|
|
35
|
+
:failed_login_count_column,
|
|
36
|
+
:last_login_at_column,
|
|
37
|
+
:include_validations
|
|
38
|
+
|
|
39
|
+
# NOTE: nil as a value means that the value of the instance variable
|
|
40
|
+
# will be assigned as is in the subclass.
|
|
41
|
+
Plugins.inherited_instance_variables(self, :@provider => nil,
|
|
42
|
+
:@include_validations => nil,
|
|
43
|
+
:@digest_column => nil)
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
module InstanceMethods
|
|
48
|
+
attr_accessor :password_confirmation
|
|
49
|
+
attr_reader :password
|
|
50
|
+
def password=(unencrypted)
|
|
51
|
+
@password = unencrypted
|
|
52
|
+
self.send "#{model.digest_column}=",model.provider.encrypt(unencrypted)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def authenticate(unencrypted)
|
|
56
|
+
if model.provider.matches?(self.send(model.digest_column),unencrypted)
|
|
57
|
+
if model.login_count_column || model.last_login_at_column
|
|
58
|
+
#Update login count
|
|
59
|
+
self.send("#{model.login_count_column}=",self.send(model.login_count_column)+1 ) if model.login_count_column
|
|
60
|
+
self.send("#{model.last_login_at_column}=",Time.now ) if model.last_login_at_column
|
|
61
|
+
self.save
|
|
62
|
+
end
|
|
63
|
+
self
|
|
64
|
+
else
|
|
65
|
+
if model.failed_login_count_column
|
|
66
|
+
#Update failed login count
|
|
67
|
+
self.send("#{model.failed_login_count_column}=",self.send(model.failed_login_count_column)+1 )
|
|
68
|
+
self.save
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def reset_access_token
|
|
74
|
+
if model.access_token_column
|
|
75
|
+
self.update(model.access_token_column=>SecureRandom.urlsafe_base64(16))
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def validate
|
|
80
|
+
super
|
|
81
|
+
|
|
82
|
+
if model.include_validations
|
|
83
|
+
errors.add :password, 'is not present' if password.nil? && new?
|
|
84
|
+
errors.add :password, 'doesn\'t match confirmation' if password != password_confirmation
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: sequel_auth
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.6
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Fatih GENÇ
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2021-05-03 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: sequel
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '5.0'
|
|
20
|
+
- - ">="
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: 5.0.0
|
|
23
|
+
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - "~>"
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '5.0'
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 5.0.0
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: bcrypt
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '3.1'
|
|
40
|
+
type: :runtime
|
|
41
|
+
prerelease: false
|
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '3.1'
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: scrypt
|
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.0'
|
|
54
|
+
type: :runtime
|
|
55
|
+
prerelease: false
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '3.0'
|
|
61
|
+
- !ruby/object:Gem::Dependency
|
|
62
|
+
name: rspec
|
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.0'
|
|
68
|
+
type: :development
|
|
69
|
+
prerelease: false
|
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '3.0'
|
|
75
|
+
- !ruby/object:Gem::Dependency
|
|
76
|
+
name: sqlite3
|
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '1.4'
|
|
82
|
+
type: :development
|
|
83
|
+
prerelease: false
|
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '1.4'
|
|
89
|
+
description: Plugin to add authentication methods to Sequel Model
|
|
90
|
+
email: fatihgnc@gmail.com
|
|
91
|
+
executables: []
|
|
92
|
+
extensions: []
|
|
93
|
+
extra_rdoc_files: []
|
|
94
|
+
files:
|
|
95
|
+
- lib/providers/bcrypt.rb
|
|
96
|
+
- lib/providers/crypt.rb
|
|
97
|
+
- lib/providers/scrypt.rb
|
|
98
|
+
- lib/sequel_auth.rb
|
|
99
|
+
- lib/sequel_auth/version.rb
|
|
100
|
+
homepage: https://gitlab.com/ikilifikir/sequel_auth
|
|
101
|
+
licenses:
|
|
102
|
+
- MIT
|
|
103
|
+
metadata: {}
|
|
104
|
+
post_install_message:
|
|
105
|
+
rdoc_options: []
|
|
106
|
+
require_paths:
|
|
107
|
+
- lib
|
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
109
|
+
requirements:
|
|
110
|
+
- - ">="
|
|
111
|
+
- !ruby/object:Gem::Version
|
|
112
|
+
version: '0'
|
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
requirements: []
|
|
119
|
+
rubygems_version: 3.2.15
|
|
120
|
+
signing_key:
|
|
121
|
+
specification_version: 4
|
|
122
|
+
summary: Plugin to add authentication methods to Sequel Model Select one of crypt,
|
|
123
|
+
bcrypt, scrypt
|
|
124
|
+
test_files: []
|