lite-uxid 1.2.0 → 1.4.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: 8119c92432950cdd4fd849aafd041832a8f4ceee022c7f38009681726bb1181a
4
- data.tar.gz: 121d26ff5203b65b8a4b148f9f82aad5585c4baeae6ae1008e71cc057d6fc1f8
3
+ metadata.gz: 1f8fdc0fac3f66d26f1fa5ed7944775912fedb7ef4a8c1d8d582ca3b8ddad11c
4
+ data.tar.gz: 9e0b2729d115fab68c449034c95ce38706680eaf0327a1f46bea2e4afb654a66
5
5
  SHA512:
6
- metadata.gz: 4ed1ddf45549eef5ee6b6950b000272b8d62dfa8ac5b403fa5e6ffc70dfabd9a03978a7e96259184b3222b42e3b1dc240e44984ee89086cfe3f396e7fcfa3d8c
7
- data.tar.gz: c63df74d2affbda2f3fefc86a0b5d44364dfef7417b22c6c56f7d411808d3935d1b26f06de92d8699f3ababaf8c84a9e3a0149123a3ed66d52e92bf59f064192
6
+ metadata.gz: 8cdb90bf7523761fe7fe9673195d888419ffc5fd0199c52bd353e39b779746b5e4bbe7e18232baf97a8bfd106afb0eb593e68818eac886aa5cc17cfa20a6bc56
7
+ data.tar.gz: 07c960b84a617349cd65c74639dbf3fee6e82ea519d0bf64ff3f52dcb75b8e6b8ff3d06c935cd58170e5987ed06ff5b47913bce7866964e24abe935c6749b383
data/CHANGELOG.md CHANGED
@@ -6,9 +6,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.4.0] - 2022-11-20
10
+ ### Changed
11
+ - Improved global config flexibility
12
+ - Update config generator to generate dynamic salt
13
+
14
+ ## [1.3.0] - 2022-11-20
15
+ ### Added
16
+ - Added uuid option
17
+
9
18
  ## [1.2.0] - 2022-11-19
10
19
  ### Added
11
- - Added individual character and length options
20
+ - Added individual character and size options
12
21
  ### Changed
13
22
  - Improved docs
14
23
  - Improved internal setup
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lite-uxid (1.2.0)
4
+ lite-uxid (1.4.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
 
6
6
  Lite::Uxid is a library for generating or obfuscating ID's based on different patterns.
7
7
  It's very useful to hide the number of resources in your database and protect against enumeration attacks.
8
+ By default, it implements websafe variants of each type.
8
9
 
9
10
  ## Installation
10
11
 
@@ -25,9 +26,11 @@ Or install it yourself as:
25
26
  ## Table of Contents
26
27
 
27
28
  * [Configuration](#configuration)
29
+ * [Usage](#usage)
28
30
  * [Hashid](#hashid)
29
31
  * [NanoID](#nanoid)
30
32
  * [ULID](#ulid)
33
+ * [UUID](#uuid)
31
34
  * [Options](#options)
32
35
  * [ActiveRecord](#active_record)
33
36
  * [Benchmarks](#benchmarks)
@@ -39,37 +42,60 @@ Or install it yourself as:
39
42
 
40
43
  ```ruby
41
44
  Lite::Uxid.configure do |config|
42
- config.encoding_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
43
- config.encoding_salt = 1_369_136
44
- config.hashid_length = 12
45
- config.nanoid_length = 21
46
- config.ulid_length = 26
45
+ config.hashid_charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
46
+ config.hashid_salt = 1_369_136
47
+ config.hashid_size = 16
48
+ config.nanoid_charset = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
49
+ config.nanoid_size = 21
50
+ config.ulid_charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
51
+ config.ulid_size = 26
47
52
  end
48
53
  ```
49
54
 
55
+ ## Usage
56
+
57
+ #### Instance
58
+ ```ruby
59
+ coder = Lite::Uxid::Hashid.new(10, size: 12)
60
+ coder.encode #=> '67wGI0'
61
+ ```
62
+
63
+ #### Class
64
+ ```ruby
65
+ Lite::Uxid::Hashid.decode('67wGI0', size: 12) #=> 10
66
+ ```
67
+
50
68
  ## Hashid
51
69
 
52
- Hashid's are reversible and is the most performant generator.
70
+ [More information](https://hashids.org)
53
71
 
54
72
  ```ruby
55
- Lite::Uxid::Hashid.encode(10) #=> 'q5D8inm0'
56
- Lite::Uxid::Hashid.decode('q5D8inm0') #=> 10
73
+ Lite::Uxid::Hashid.encode(10) #=> '1zWr1m0'
74
+ Lite::Uxid::Hashid.decode('1zWr1m0') #=> 10
57
75
  ```
58
76
 
59
77
  ## NanoID
60
78
 
61
- NanoID are irreversible and are the second fastest ID generator but while unlikely can produce collisions.
79
+ [More information](https://github.com/ai/nanoid)
62
80
 
63
81
  ```ruby
64
- Lite::Uxid::Nanoid.encode #=> '0bmHjB5Gx8FTBqJekX6dS6XIXf'
82
+ Lite::Uxid::Nanoid.encode #=> 'sMuNUa3Cegn6r5GRQ4Ij2'
65
83
  ```
66
84
 
67
85
  ## ULID
68
86
 
69
- ULID are irreversible but provide information outside of just randomness.
87
+ [More information](https://github.com/ulid/spec)
70
88
 
71
89
  ```ruby
72
- Lite::Uxid::Ulid.encode #=> '1mqfg9qa96s8s5f02o1ucf8lcc'
90
+ Lite::Uxid::Ulid.encode #=> '01GJAY9KGR539EZF4QWYEJGSN7'
91
+ ```
92
+
93
+ ## UUID
94
+
95
+ Implements v4 of the specification. [More information](https://en.wikipedia.org/wiki/Universally_unique_identifier)
96
+
97
+ ```ruby
98
+ Lite::Uxid::Uuid.encode #=> '4376a67e-1189-44b3-a599-7f7566bf105b'
73
99
  ```
74
100
 
75
101
  ## Options
@@ -77,7 +103,7 @@ Lite::Uxid::Ulid.encode #=> '1mqfg9qa96s8s5f02o1ucf8lcc'
77
103
  Local options can be passed to override global options.
78
104
 
79
105
  ```ruby
80
- Lite::Uxid::Ulid.encode(chars: 'abc123', length: 12) #=> 'a3b12c12c3ca'
106
+ Lite::Uxid::Ulid.encode(chars: 'abc123', size: 12) #=> 'a3b12c12c3ca'
81
107
  ```
82
108
 
83
109
  ## ActiveRecord
@@ -115,6 +141,13 @@ class User < ActiveRecord::Base
115
141
  end
116
142
  ```
117
143
 
144
+ #### UUID
145
+ ```ruby
146
+ class User < ActiveRecord::Base
147
+ include Lite::Uxid::Record::Uuid
148
+ end
149
+ ```
150
+
118
151
  **Usage**
119
152
 
120
153
  Using one of the mixins above provides a handy method to find records by uxid.
@@ -134,10 +167,15 @@ User.find_by_uxid!('x123') #=> Raises an ActiveRecord::RecordNotFound error if n
134
167
 
135
168
  ## Benchmarks
136
169
 
137
- The classes ranked from fastest to slowest are `Hashid`, `Nanoid`, and `Ulid`.
170
+ The classes ranked from fastest to slowest are `UUID`, `Hashid`, `Nanoid`, and `Ulid`.
138
171
 
139
172
  View how each compares by running the [benchmarks](https://github.com/drexed/lite-uxid/tree/master/benchmarks).
140
173
 
174
+ #### Alternatives
175
+
176
+ Learn more about alternative functions and more advance hashing setups:
177
+ [hashids.org](https://hashids.org)
178
+
141
179
  ## Development
142
180
 
143
181
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -7,16 +7,24 @@ require "lite/uxid"
7
7
 
8
8
  Benchmark.ips do |x|
9
9
  x.report("Hashid") do
10
- Lite::Uxid::Hashid.encode(rand(1..1_000_000))
10
+ id = rand(1..1_000_000)
11
+ Lite::Uxid::Hashid.encode(id)
11
12
  end
12
13
 
13
14
  x.report("NanoID") do
15
+ _id = rand(1..1_000_000) # To simulate the extra work from `rand`
14
16
  Lite::Uxid::Nanoid.encode
15
17
  end
16
18
 
17
19
  x.report("ULID") do
20
+ _id = rand(1..1_000_000) # To simulate the extra work from `rand`
18
21
  Lite::Uxid::Ulid.encode
19
22
  end
20
23
 
24
+ x.report("UUID") do
25
+ _id = rand(1..1_000_000) # To simulate the extra work from `rand`
26
+ Lite::Uxid::Uuid.encode
27
+ end
28
+
21
29
  x.compare!
22
30
  end
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Lite::Uxid.configure do |config|
4
- config.encoding_chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
5
- config.encoding_salt = 1_369_136
6
- config.hashid_length = 12
7
- config.nanoid_length = 21
8
- config.ulid_length = 26
4
+ config.hashid_charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
5
+ config.hashid_salt = 1_369_136
6
+ config.hashid_size = 16
7
+ config.nanoid_charset = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
8
+ config.nanoid_size = 21
9
+ config.ulid_charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
10
+ config.ulid_size = 26
9
11
  end
@@ -5,14 +5,16 @@ module Lite
5
5
 
6
6
  class Configuration
7
7
 
8
- attr_accessor :encoding_chars, :encoding_salt, :hashid_length, :nanoid_length, :ulid_length
8
+ attr_accessor :hashid_charset, :hashid_salt, :hashid_size, :nanoid_charset, :nanoid_size, :ulid_charset, :ulid_size
9
9
 
10
10
  def initialize
11
- @encoding_chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
12
- @encoding_salt = 1_369_136
13
- @hashid_length = 12
14
- @nanoid_length = 21
15
- @ulid_length = 26
11
+ @hashid_charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
12
+ @hashid_salt = 1_369_136
13
+ @hashid_size = 16
14
+ @nanoid_charset = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
15
+ @nanoid_size = 21
16
+ @ulid_charset = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
17
+ @ulid_size = 26
16
18
  end
17
19
 
18
20
  end
@@ -5,11 +5,11 @@ module Lite
5
5
  class Hashid < Reversible
6
6
 
7
7
  def encode
8
- encode_chars((id + coder_salt) << coder_length)
8
+ encode_chars((id + coder_salt) << coder_size)
9
9
  end
10
10
 
11
11
  def decode
12
- (decode_chars(id) >> coder_length) - coder_salt
12
+ (decode_chars(id) >> coder_size) - coder_salt
13
13
  end
14
14
 
15
15
  private
@@ -21,8 +21,8 @@ module Lite
21
21
  str = ""
22
22
 
23
23
  while decoded_id.positive?
24
- str = "#{coder_chars[decoded_id % coder_base]}#{str}"
25
- decoded_id /= coder_base
24
+ str = "#{coder_charset[decoded_id % coder_length]}#{str}"
25
+ decoded_id /= coder_length
26
26
  end
27
27
 
28
28
  str
@@ -31,12 +31,12 @@ module Lite
31
31
  def decode_chars(encoded_id)
32
32
  pos = 0
33
33
  num = 0
34
- len = encoded_id.length
34
+ len = encoded_id.size
35
35
  max = len - 1
36
36
 
37
37
  while pos < len
38
- pow = coder_base**(max - pos)
39
- num += coder_chars.index(encoded_id[pos]) * pow
38
+ pow = coder_length**(max - pos)
39
+ num += coder_charset.index(encoded_id[pos]) * pow
40
40
  pos += 1
41
41
  end
42
42
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "securerandom" unless defined?(SecureRandom)
4
+
3
5
  module Lite
4
6
  module Uxid
5
7
  class Irreversible
@@ -34,14 +36,14 @@ module Lite
34
36
 
35
37
  private
36
38
 
37
- def coder_base
38
- @coder_base ||= coder_chars.length
39
+ def coder_bytes
40
+ @coder_bytes ||= SecureRandom.random_bytes(coder_size).bytes
39
41
  end
40
42
 
41
- def coder_chars
42
- @coder_chars ||=
43
- opts.delete(:chars) ||
44
- Lite::Uxid.configuration.encoding_chars
43
+ def coder_charset
44
+ @coder_charset ||=
45
+ opts.delete(:charset) ||
46
+ Lite::Uxid.configuration.send("#{coder_class.downcase}_charset")
45
47
  end
46
48
 
47
49
  def coder_class
@@ -49,15 +51,19 @@ module Lite
49
51
  end
50
52
 
51
53
  def coder_length
52
- @coder_length ||=
53
- opts.delete(:length) ||
54
- Lite::Uxid.configuration.send("#{coder_class.downcase}_length")
54
+ @coder_length ||= coder_charset.size
55
55
  end
56
56
 
57
57
  def coder_salt
58
58
  @coder_salt ||=
59
59
  opts.delete(:salt) ||
60
- Lite::Uxid.configuration.encoding_salt
60
+ Lite::Uxid.configuration.send("#{coder_class.downcase}_salt")
61
+ end
62
+
63
+ def coder_size
64
+ @coder_size ||=
65
+ opts.delete(:size) ||
66
+ Lite::Uxid.configuration.send("#{coder_class.downcase}_size")
61
67
  end
62
68
 
63
69
  end
@@ -5,7 +5,9 @@ module Lite
5
5
  class Nanoid < Irreversible
6
6
 
7
7
  def encode
8
- coder_chars.chars.sample(coder_length).join
8
+ (0...coder_size).each_with_object(+"") do |i, str|
9
+ str << coder_charset[coder_bytes[i] & 63]
10
+ end
9
11
  end
10
12
 
11
13
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support" unless defined?(ActiveSupport)
4
+
5
+ module Lite
6
+ module Uxid
7
+ module Record
8
+ module Uuid
9
+
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ before_create :callback_generate_uxid!, if: proc { respond_to?(:uxid) && !uxid? }
14
+ end
15
+
16
+ private
17
+
18
+ def callback_generate_uxid!
19
+ self.uxid = Lite::Uxid::Uuid.encode
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "securerandom" unless defined?(SecureRandom)
4
-
5
3
  module Lite
6
4
  module Uxid
7
5
  class Ulid < Irreversible
@@ -10,11 +8,11 @@ module Lite
10
8
 
11
9
  def encode
12
10
  oct = octect
13
- ele = "0" * coder_length
14
- pos = coder_length - 1
11
+ ele = "0" * coder_size
12
+ pos = coder_size - 1
15
13
 
16
14
  while oct.positive?
17
- ele[pos] = coder_chars[oct & MASK]
15
+ ele[pos] = coder_charset[oct & MASK]
18
16
  oct >>= 5
19
17
  pos -= 1
20
18
  end
@@ -35,7 +33,7 @@ module Lite
35
33
 
36
34
  def unixtime_ms
37
35
  time = Time.respond_to?(:current) ? Time.current : Time.now
38
- (time.to_f * 1_000).to_i
36
+ time.to_i * 1_000
39
37
  end
40
38
 
41
39
  def unixtime_48bit
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lite
4
+ module Uxid
5
+ class Uuid < Irreversible
6
+
7
+ def encode
8
+ SecureRandom.uuid
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -3,7 +3,7 @@
3
3
  module Lite
4
4
  module Uxid
5
5
 
6
- VERSION = "1.2.0"
6
+ VERSION = "1.4.0"
7
7
 
8
8
  end
9
9
  end
data/lib/lite/uxid.rb CHANGED
@@ -9,6 +9,8 @@ require "lite/uxid/reversible"
9
9
  require "lite/uxid/record/hashid"
10
10
  require "lite/uxid/record/nanoid"
11
11
  require "lite/uxid/record/ulid"
12
+ require "lite/uxid/record/uuid"
12
13
  require "lite/uxid/hashid"
13
14
  require "lite/uxid/nanoid"
14
15
  require "lite/uxid/ulid"
16
+ require "lite/uxid/uuid"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lite-uxid
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-19 00:00:00.000000000 Z
11
+ date: 2022-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -224,8 +224,10 @@ files:
224
224
  - lib/lite/uxid/record/hashid.rb
225
225
  - lib/lite/uxid/record/nanoid.rb
226
226
  - lib/lite/uxid/record/ulid.rb
227
+ - lib/lite/uxid/record/uuid.rb
227
228
  - lib/lite/uxid/reversible.rb
228
229
  - lib/lite/uxid/ulid.rb
230
+ - lib/lite/uxid/uuid.rb
229
231
  - lib/lite/uxid/version.rb
230
232
  - lite-uxid.gemspec
231
233
  homepage: http://drexed.github.io/lite-uxid