lite-uxid 1.2.0 → 1.4.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 +10 -1
- data/Gemfile.lock +1 -1
- data/README.md +52 -14
- data/benchmarks/compare.rb +9 -1
- data/lib/generators/lite/uxid/templates/install.rb +7 -5
- data/lib/lite/uxid/configuration.rb +8 -6
- data/lib/lite/uxid/hashid.rb +7 -7
- data/lib/lite/uxid/irreversible.rb +16 -10
- data/lib/lite/uxid/nanoid.rb +3 -1
- data/lib/lite/uxid/record/uuid.rb +25 -0
- data/lib/lite/uxid/ulid.rb +4 -6
- data/lib/lite/uxid/uuid.rb +13 -0
- data/lib/lite/uxid/version.rb +1 -1
- data/lib/lite/uxid.rb +2 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f8fdc0fac3f66d26f1fa5ed7944775912fedb7ef4a8c1d8d582ca3b8ddad11c
|
4
|
+
data.tar.gz: 9e0b2729d115fab68c449034c95ce38706680eaf0327a1f46bea2e4afb654a66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
20
|
+
- Added individual character and size options
|
12
21
|
### Changed
|
13
22
|
- Improved docs
|
14
23
|
- Improved internal setup
|
data/Gemfile.lock
CHANGED
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.
|
43
|
-
config.
|
44
|
-
config.
|
45
|
-
config.
|
46
|
-
config.
|
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
|
-
|
70
|
+
[More information](https://hashids.org)
|
53
71
|
|
54
72
|
```ruby
|
55
|
-
Lite::Uxid::Hashid.encode(10)
|
56
|
-
Lite::Uxid::Hashid.decode('
|
73
|
+
Lite::Uxid::Hashid.encode(10) #=> '1zWr1m0'
|
74
|
+
Lite::Uxid::Hashid.decode('1zWr1m0') #=> 10
|
57
75
|
```
|
58
76
|
|
59
77
|
## NanoID
|
60
78
|
|
61
|
-
|
79
|
+
[More information](https://github.com/ai/nanoid)
|
62
80
|
|
63
81
|
```ruby
|
64
|
-
Lite::Uxid::Nanoid.encode #=> '
|
82
|
+
Lite::Uxid::Nanoid.encode #=> 'sMuNUa3Cegn6r5GRQ4Ij2'
|
65
83
|
```
|
66
84
|
|
67
85
|
## ULID
|
68
86
|
|
69
|
-
|
87
|
+
[More information](https://github.com/ulid/spec)
|
70
88
|
|
71
89
|
```ruby
|
72
|
-
Lite::Uxid::Ulid.encode #=> '
|
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',
|
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.
|
data/benchmarks/compare.rb
CHANGED
@@ -7,16 +7,24 @@ require "lite/uxid"
|
|
7
7
|
|
8
8
|
Benchmark.ips do |x|
|
9
9
|
x.report("Hashid") do
|
10
|
-
|
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.
|
5
|
-
config.
|
6
|
-
config.
|
7
|
-
config.
|
8
|
-
config.
|
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 :
|
8
|
+
attr_accessor :hashid_charset, :hashid_salt, :hashid_size, :nanoid_charset, :nanoid_size, :ulid_charset, :ulid_size
|
9
9
|
|
10
10
|
def initialize
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@
|
14
|
-
@
|
15
|
-
@
|
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
|
data/lib/lite/uxid/hashid.rb
CHANGED
@@ -5,11 +5,11 @@ module Lite
|
|
5
5
|
class Hashid < Reversible
|
6
6
|
|
7
7
|
def encode
|
8
|
-
encode_chars((id + coder_salt) <<
|
8
|
+
encode_chars((id + coder_salt) << coder_size)
|
9
9
|
end
|
10
10
|
|
11
11
|
def decode
|
12
|
-
(decode_chars(id) >>
|
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 = "#{
|
25
|
-
decoded_id /=
|
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.
|
34
|
+
len = encoded_id.size
|
35
35
|
max = len - 1
|
36
36
|
|
37
37
|
while pos < len
|
38
|
-
pow =
|
39
|
-
num +=
|
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
|
38
|
-
@
|
39
|
+
def coder_bytes
|
40
|
+
@coder_bytes ||= SecureRandom.random_bytes(coder_size).bytes
|
39
41
|
end
|
40
42
|
|
41
|
-
def
|
42
|
-
@
|
43
|
-
opts.delete(:
|
44
|
-
Lite::Uxid.configuration.
|
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.
|
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
|
data/lib/lite/uxid/nanoid.rb
CHANGED
@@ -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
|
data/lib/lite/uxid/ulid.rb
CHANGED
@@ -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" *
|
14
|
-
pos =
|
11
|
+
ele = "0" * coder_size
|
12
|
+
pos = coder_size - 1
|
15
13
|
|
16
14
|
while oct.positive?
|
17
|
-
ele[pos] =
|
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
|
-
|
36
|
+
time.to_i * 1_000
|
39
37
|
end
|
40
38
|
|
41
39
|
def unixtime_48bit
|
data/lib/lite/uxid/version.rb
CHANGED
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.
|
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-
|
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
|