uid2 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/.github/workflows/main.yml +1 -1
- data/Gemfile +3 -6
- data/Gemfile.lock +96 -0
- data/README.md +27 -10
- data/lib/faraday/uid2/middleware.rb +76 -0
- data/lib/faraday/uid2.rb +8 -0
- data/lib/uid2/client.rb +21 -57
- data/lib/uid2/version.rb +1 -1
- data/lib/uid2.rb +2 -0
- data/uid2.gemspec +8 -8
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63c73ef45bda732e21922cc4f6a8fab9ed68471f1361cac468bef5199934ceb9
|
4
|
+
data.tar.gz: 4fcdfbc699215daddd062b2032fdd5b0640817eca754ea6a584111a893f0df4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57d5aa6003cd365972157c588493fbb5b90508e1e681ed3ad5fa563dd814fbabad419129665c07c96b1ae10a516dfd95348de825ede173a8a03bb4f19366dd3c
|
7
|
+
data.tar.gz: 838a537bce16ff6d5cb0c24a4373737a7b46dda1309b1d987d8cfcb4032a64454ddb7e8c50c8d7b81751b6a3f58c8f4e0423701c681430b32942e2a6f970f3c5
|
data/.github/workflows/main.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
uid2 (0.2.0)
|
5
|
+
faraday (>= 1)
|
6
|
+
faraday_middleware (>= 1)
|
7
|
+
hashie (>= 4)
|
8
|
+
net-http-persistent (>= 4)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
ast (2.4.2)
|
14
|
+
connection_pool (2.2.5)
|
15
|
+
diff-lcs (1.5.0)
|
16
|
+
faraday (1.10.0)
|
17
|
+
faraday-em_http (~> 1.0)
|
18
|
+
faraday-em_synchrony (~> 1.0)
|
19
|
+
faraday-excon (~> 1.1)
|
20
|
+
faraday-httpclient (~> 1.0)
|
21
|
+
faraday-multipart (~> 1.0)
|
22
|
+
faraday-net_http (~> 1.0)
|
23
|
+
faraday-net_http_persistent (~> 1.0)
|
24
|
+
faraday-patron (~> 1.0)
|
25
|
+
faraday-rack (~> 1.0)
|
26
|
+
faraday-retry (~> 1.0)
|
27
|
+
ruby2_keywords (>= 0.0.4)
|
28
|
+
faraday-em_http (1.0.0)
|
29
|
+
faraday-em_synchrony (1.0.0)
|
30
|
+
faraday-excon (1.1.0)
|
31
|
+
faraday-httpclient (1.0.1)
|
32
|
+
faraday-multipart (1.0.4)
|
33
|
+
multipart-post (~> 2)
|
34
|
+
faraday-net_http (1.0.1)
|
35
|
+
faraday-net_http_persistent (1.2.0)
|
36
|
+
faraday-patron (1.0.0)
|
37
|
+
faraday-rack (1.0.0)
|
38
|
+
faraday-retry (1.0.3)
|
39
|
+
faraday_middleware (1.2.0)
|
40
|
+
faraday (~> 1.0)
|
41
|
+
hashie (5.0.0)
|
42
|
+
multipart-post (2.2.3)
|
43
|
+
net-http-persistent (4.0.1)
|
44
|
+
connection_pool (~> 2.2)
|
45
|
+
parallel (1.22.1)
|
46
|
+
parser (3.1.2.0)
|
47
|
+
ast (~> 2.4.1)
|
48
|
+
rainbow (3.1.1)
|
49
|
+
rake (13.0.6)
|
50
|
+
regexp_parser (2.5.0)
|
51
|
+
rexml (3.2.5)
|
52
|
+
rspec (3.11.0)
|
53
|
+
rspec-core (~> 3.11.0)
|
54
|
+
rspec-expectations (~> 3.11.0)
|
55
|
+
rspec-mocks (~> 3.11.0)
|
56
|
+
rspec-core (3.11.0)
|
57
|
+
rspec-support (~> 3.11.0)
|
58
|
+
rspec-expectations (3.11.0)
|
59
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
60
|
+
rspec-support (~> 3.11.0)
|
61
|
+
rspec-mocks (3.11.1)
|
62
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
63
|
+
rspec-support (~> 3.11.0)
|
64
|
+
rspec-support (3.11.0)
|
65
|
+
rubocop (1.29.1)
|
66
|
+
parallel (~> 1.10)
|
67
|
+
parser (>= 3.1.0.0)
|
68
|
+
rainbow (>= 2.2.2, < 4.0)
|
69
|
+
regexp_parser (>= 1.8, < 3.0)
|
70
|
+
rexml (>= 3.2.5, < 4.0)
|
71
|
+
rubocop-ast (>= 1.17.0, < 2.0)
|
72
|
+
ruby-progressbar (~> 1.7)
|
73
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
74
|
+
rubocop-ast (1.19.1)
|
75
|
+
parser (>= 3.1.1.0)
|
76
|
+
rubocop-performance (1.13.3)
|
77
|
+
rubocop (>= 1.7.0, < 2.0)
|
78
|
+
rubocop-ast (>= 0.4.0)
|
79
|
+
ruby-progressbar (1.11.0)
|
80
|
+
ruby2_keywords (0.0.5)
|
81
|
+
standard (1.12.1)
|
82
|
+
rubocop (= 1.29.1)
|
83
|
+
rubocop-performance (= 1.13.3)
|
84
|
+
unicode-display_width (2.2.0)
|
85
|
+
|
86
|
+
PLATFORMS
|
87
|
+
ruby
|
88
|
+
|
89
|
+
DEPENDENCIES
|
90
|
+
rake
|
91
|
+
rspec
|
92
|
+
standard
|
93
|
+
uid2!
|
94
|
+
|
95
|
+
BUNDLED WITH
|
96
|
+
2.3.16
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# UID2 - A Ruby API client for Unified ID 2.0
|
2
2
|
|
3
|
-
|
3
|
+
This gem provides an API client for [Unified ID 2.0](https://github.com/UnifiedID2/uid2docs).
|
4
4
|
|
5
|
-
|
5
|
+
Current supports UID2 API v2.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -12,17 +12,34 @@ Add this line to your application's Gemfile:
|
|
12
12
|
gem 'uid2'
|
13
13
|
```
|
14
14
|
|
15
|
-
|
15
|
+
## Usage
|
16
16
|
|
17
|
-
|
17
|
+
This gem implements every Unified ID 2.0 APIs.
|
18
18
|
|
19
|
-
|
19
|
+
To create a client:
|
20
20
|
|
21
|
-
|
21
|
+
```ruby
|
22
|
+
client = Uid2::Client.new do |client|
|
23
|
+
c.bearer_token = "YOUR_TOKEN_HERE"
|
24
|
+
c.secret_key = "YOUR_SECRET_KEY_HERE"
|
25
|
+
end
|
26
|
+
```
|
22
27
|
|
23
|
-
|
28
|
+
Then call methods:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
# To generate UID2 token
|
32
|
+
client.generate_token(email: 'foo@bar.com')
|
33
|
+
client.generate_token(phone: '+886912345678')
|
34
|
+
|
35
|
+
# To map UID2 identity
|
36
|
+
client.generate_identifier(email: 'foo@bar.com')
|
37
|
+
client.generate_identifier(phone: '+886912345678')
|
38
|
+
|
39
|
+
# To get salt buckets
|
40
|
+
client.get_salt_buckets
|
41
|
+
```
|
24
42
|
|
25
|
-
TODO: Write usage instructions here
|
26
43
|
|
27
44
|
## Development
|
28
45
|
|
@@ -32,7 +49,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
49
|
|
33
50
|
## Contributing
|
34
51
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
52
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/polydice/uid2. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/uid2/blob/main/CODE_OF_CONDUCT.md).
|
36
53
|
|
37
54
|
## License
|
38
55
|
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "faraday"
|
4
|
+
require "base64"
|
5
|
+
require "hashie/mash"
|
6
|
+
|
7
|
+
module Faraday
|
8
|
+
module Uid2
|
9
|
+
class Middleware < Faraday::Middleware
|
10
|
+
def initialize(app, secret_key, is_refresh, options = {})
|
11
|
+
super(app, options)
|
12
|
+
|
13
|
+
@key = Base64.decode64(secret_key)
|
14
|
+
@is_refresh = is_refresh
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(request_env)
|
18
|
+
unless @is_refresh
|
19
|
+
@nonce = Random.new.bytes(8)
|
20
|
+
|
21
|
+
cipher = create_cipher.encrypt
|
22
|
+
iv = cipher.random_iv
|
23
|
+
|
24
|
+
body = request_env.body
|
25
|
+
payload = timestamp_bytes + @nonce + body
|
26
|
+
encrypted = cipher.update(payload) + cipher.final
|
27
|
+
request_env.body = Base64.strict_encode64(["\x1", iv, encrypted, cipher.auth_tag].join)
|
28
|
+
end
|
29
|
+
|
30
|
+
@app.call(request_env).on_complete do |response_env|
|
31
|
+
process_response(response_env)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def process_response(env)
|
36
|
+
resp = Base64.decode64(env.body).unpack("C*")
|
37
|
+
iv = resp[0..11].pack("C*")
|
38
|
+
cipher_text = resp[12...-16].pack("C*")
|
39
|
+
auth_tag = resp[-16...-1].pack("C*")
|
40
|
+
|
41
|
+
cipher = create_cipher.decrypt
|
42
|
+
cipher.iv = iv
|
43
|
+
cipher.auth_tag = auth_tag
|
44
|
+
|
45
|
+
payload = cipher.update(cipher_text) + cipher.final
|
46
|
+
|
47
|
+
data = if @is_refresh
|
48
|
+
payload
|
49
|
+
else
|
50
|
+
timestamp = Time.at(payload[0..7].unpack1("Q>") / 1000.0)
|
51
|
+
raise Faraday::ParsingError.new("Response timestamp is too old", env[:response]) if Time.now - timestamp > 5 * 60
|
52
|
+
|
53
|
+
nonce = payload[8..15]
|
54
|
+
raise Faraday::ParsingError.new("Nonce mismatch", env[:response]) if nonce != @nonce
|
55
|
+
|
56
|
+
payload[16..]
|
57
|
+
end
|
58
|
+
|
59
|
+
env.response_headers["Content-Type"] = "application/json"
|
60
|
+
env.body = Hashie::Mash.new(JSON.parse(data))
|
61
|
+
end
|
62
|
+
|
63
|
+
def timestamp_bytes
|
64
|
+
[(Time.now.to_f * 1000).to_i].pack("Q>")
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_cipher
|
68
|
+
cipher = OpenSSL::Cipher.new("aes-256-gcm").encrypt
|
69
|
+
cipher.padding = 0
|
70
|
+
cipher.key = @key
|
71
|
+
cipher.auth_data = ""
|
72
|
+
cipher
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/faraday/uid2.rb
ADDED
data/lib/uid2/client.rb
CHANGED
@@ -3,77 +3,45 @@
|
|
3
3
|
require "net/http/persistent"
|
4
4
|
require "faraday"
|
5
5
|
require "faraday_middleware"
|
6
|
+
require "faraday/uid2"
|
6
7
|
require "time"
|
7
8
|
|
8
9
|
module Uid2
|
9
10
|
class Client
|
10
|
-
attr_accessor :bearer_token, :base_url
|
11
|
+
attr_accessor :bearer_token, :base_url, :secret_key
|
11
12
|
|
12
13
|
def initialize(_options = {})
|
13
14
|
yield(self) if block_given?
|
14
15
|
|
15
|
-
self.base_url ||= "https://
|
16
|
+
self.base_url ||= "https://prod.uidapi.com/v2/"
|
16
17
|
end
|
17
18
|
|
18
|
-
def generate_token(email: nil, email_hash: nil)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# only the email will return a mapping response.
|
23
|
-
params = if email.empty?
|
24
|
-
{ email_hash: email_hash }
|
25
|
-
else
|
26
|
-
{ email: email }
|
27
|
-
end
|
28
|
-
http.get("token/generate", params).body
|
19
|
+
def generate_token(email: nil, email_hash: nil, phone: nil, phone_hash: nil)
|
20
|
+
params = {email: email, email_hash: email_hash, phone: phone, phone_hash: phone_hash}.reject { |_, v| v.nil? }
|
21
|
+
raise ArgumentError, "One of the argument needs to be provided" if params.empty?
|
22
|
+
http.post("token/generate", params).body
|
29
23
|
end
|
30
24
|
|
31
|
-
def validate_token(token:, email: nil, email_hash: nil)
|
32
|
-
|
33
|
-
|
34
|
-
params = if email.empty?
|
35
|
-
{ email_hash: email_hash }
|
36
|
-
else
|
37
|
-
{ email: email }
|
38
|
-
end
|
25
|
+
def validate_token(token:, email: nil, email_hash: nil, phone: nil, phone_hash: nil)
|
26
|
+
params = {email: email, email_hash: email_hash, phone: phone, phone_hash: phone_hash}.reject { |_, v| v.nil? }
|
27
|
+
raise ArgumentError, "One of the argument needs to be provided" if params.empty?
|
39
28
|
|
40
|
-
http.
|
29
|
+
http.post("token/validate", params.merge(token: token)).body
|
41
30
|
end
|
42
31
|
|
43
|
-
def refresh_token(refresh_token:)
|
44
|
-
http.
|
32
|
+
def refresh_token(refresh_token:, refresh_response_key:)
|
33
|
+
http(is_refresh: true, refresh_response_key: refresh_response_key).post("token/refresh", refresh_token).body
|
45
34
|
end
|
46
35
|
|
47
36
|
def get_salt_buckets(since: Time.now)
|
48
37
|
# By default, Ruby's iso8601 generates timezone parts (`T`)
|
49
38
|
# which needs to be removed for UID2 APIs
|
50
|
-
http.
|
39
|
+
http.post("identity/buckets", since_timestamp: since.utc.iso8601[0..-2]).body
|
51
40
|
end
|
52
41
|
|
53
|
-
def generate_identifier(email: nil, email_hash: nil)
|
54
|
-
|
55
|
-
|
56
|
-
# As stated in doc, if email and email_hash are both supplied in the same request,
|
57
|
-
# only the email will return a mapping response.
|
58
|
-
params = if email.empty?
|
59
|
-
{ email_hash: email_hash }
|
60
|
-
else
|
61
|
-
{ email: email }
|
62
|
-
end
|
63
|
-
|
64
|
-
http.get("identity/map", params).body
|
65
|
-
end
|
66
|
-
|
67
|
-
def batch_generate_identifier(email: nil, email_hash: nil)
|
68
|
-
raise ArgumentError, "Either email or email_hash needs to be provided" if email.nil? && email_hash.nil?
|
69
|
-
|
70
|
-
# As stated in doc, if email and email_hash are both supplied in the same request,
|
71
|
-
# only the email will return a mapping response.
|
72
|
-
params = if email.empty?
|
73
|
-
{ email_hash: Array(email_hash) }
|
74
|
-
else
|
75
|
-
{ email: Array(email) }
|
76
|
-
end
|
42
|
+
def generate_identifier(email: nil, email_hash: nil, phone: nil, phone_hash: nil)
|
43
|
+
params = {email: Array(email), email_hash: Array(email_hash), phone: Array(phone), phone_hash: Array(phone_hash)}.reject { |_, v| v.empty? }
|
44
|
+
raise ArgumentError, "One of the argument needs to be provided" if params.empty?
|
77
45
|
|
78
46
|
http.post("identity/map", params).body
|
79
47
|
end
|
@@ -86,17 +54,13 @@ module Uid2
|
|
86
54
|
}
|
87
55
|
end
|
88
56
|
|
89
|
-
def http
|
90
|
-
|
57
|
+
def http(is_refresh: false, refresh_response_key: nil)
|
58
|
+
Faraday.new(
|
91
59
|
url: base_url,
|
92
60
|
headers: credentials
|
93
61
|
) do |f|
|
94
|
-
f.request :json
|
95
|
-
|
96
|
-
f.response :raise_error
|
97
|
-
f.response :mashify
|
98
|
-
f.response :json
|
99
|
-
|
62
|
+
f.request :json unless refresh_response_key
|
63
|
+
f.request :uid2_encryption, refresh_response_key || secret_key, is_refresh
|
100
64
|
f.adapter :net_http_persistent
|
101
65
|
end
|
102
66
|
end
|
data/lib/uid2/version.rb
CHANGED
data/lib/uid2.rb
CHANGED
data/uid2.gemspec
CHANGED
@@ -3,15 +3,15 @@
|
|
3
3
|
require_relative "lib/uid2/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name
|
7
|
-
spec.version
|
8
|
-
spec.authors
|
9
|
-
spec.email
|
6
|
+
spec.name = "uid2"
|
7
|
+
spec.version = Uid2::VERSION
|
8
|
+
spec.authors = ["Richard Lee"]
|
9
|
+
spec.email = ["14349+dlackty@users.noreply.github.com"]
|
10
10
|
|
11
|
-
spec.summary
|
12
|
-
spec.description
|
13
|
-
spec.homepage
|
14
|
-
spec.license
|
11
|
+
spec.summary = "Ruby API client for Unified ID 2.0"
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = "https://github.com/polydice/uid2"
|
14
|
+
spec.license = "MIT"
|
15
15
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uid2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Lee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -80,11 +80,14 @@ files:
|
|
80
80
|
- CHANGELOG.md
|
81
81
|
- CODE_OF_CONDUCT.md
|
82
82
|
- Gemfile
|
83
|
+
- Gemfile.lock
|
83
84
|
- LICENSE.txt
|
84
85
|
- README.md
|
85
86
|
- Rakefile
|
86
87
|
- bin/console
|
87
88
|
- bin/setup
|
89
|
+
- lib/faraday/uid2.rb
|
90
|
+
- lib/faraday/uid2/middleware.rb
|
88
91
|
- lib/uid2.rb
|
89
92
|
- lib/uid2/client.rb
|
90
93
|
- lib/uid2/version.rb
|
@@ -111,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
114
|
- !ruby/object:Gem::Version
|
112
115
|
version: '0'
|
113
116
|
requirements: []
|
114
|
-
rubygems_version: 3.1.
|
117
|
+
rubygems_version: 3.1.6
|
115
118
|
signing_key:
|
116
119
|
specification_version: 4
|
117
120
|
summary: Ruby API client for Unified ID 2.0
|