uid2 0.1.0 → 0.2.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: ca62bf4baf03040acd589422b287455bf830b29b7169754a18dd8191dc031e4f
4
- data.tar.gz: 34f3b2736cc70383184cb69ea742e73469e06a274cabfcb53275081698cdc982
3
+ metadata.gz: 63c73ef45bda732e21922cc4f6a8fab9ed68471f1361cac468bef5199934ceb9
4
+ data.tar.gz: 4fcdfbc699215daddd062b2032fdd5b0640817eca754ea6a584111a893f0df4a
5
5
  SHA512:
6
- metadata.gz: b635f3d73fae3870b3a698f6c2beeffdece28daba803f590324b6f9c6a59d01d441e56b79d13410709bd4555a300149c4c9b40e1041e35c6b5e0653c5b004741
7
- data.tar.gz: 4482a0398dafb9c9af3e438ba837dbb67c0b508f2dead329cd33066b3e9c881aa4d77473fe5a2f1df8d6fc087eb86bcb32add1e8c2a46f82cde5169e7295913d
6
+ metadata.gz: 57d5aa6003cd365972157c588493fbb5b90508e1e681ed3ad5fa563dd814fbabad419129665c07c96b1ae10a516dfd95348de825ede173a8a03bb4f19366dd3c
7
+ data.tar.gz: 838a537bce16ff6d5cb0c24a4373737a7b46dda1309b1d987d8cfcb4032a64454ddb7e8c50c8d7b81751b6a3f58c8f4e0423701c681430b32942e2a6f970f3c5
@@ -10,7 +10,7 @@ jobs:
10
10
  - name: Set up Ruby
11
11
  uses: ruby/setup-ruby@v1
12
12
  with:
13
- ruby-version: 2.7.2
13
+ ruby-version: 3.1.2
14
14
  bundler-cache: true
15
15
  - name: Run the default task
16
16
  run: bundle exec rake
data/Gemfile CHANGED
@@ -2,11 +2,8 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- # Specify your gem's dependencies in uid2.gemspec
6
5
  gemspec
7
6
 
8
- gem "rake", "~> 13.0"
9
-
10
- gem "rspec", "~> 3.0"
11
-
12
- gem "rubocop", "~> 1.7"
7
+ gem "rake"
8
+ gem "rspec"
9
+ gem "standard"
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
- # Uid2
1
+ # UID2 - A Ruby API client for Unified ID 2.0
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/uid2`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ This gem provides an API client for [Unified ID 2.0](https://github.com/UnifiedID2/uid2docs).
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
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
- And then execute:
15
+ ## Usage
16
16
 
17
- $ bundle install
17
+ This gem implements every Unified ID 2.0 APIs.
18
18
 
19
- Or install it yourself as:
19
+ To create a client:
20
20
 
21
- $ gem install uid2
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
- ## Usage
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/[USERNAME]/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).
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
@@ -0,0 +1,8 @@
1
+ require_relative "uid2/middleware"
2
+ require "faraday"
3
+
4
+ module Faraday
5
+ module Uid2
6
+ Faraday::Request.register_middleware uid2_encryption: Middleware
7
+ end
8
+ end
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://integ.uidapi.com/v1/"
16
+ self.base_url ||= "https://prod.uidapi.com/v2/"
16
17
  end
17
18
 
18
- def generate_token(email: nil, email_hash: nil)
19
- raise ArgumentError, "Either email or email_hash needs to be provided" if email.nil? && email_hash.nil?
20
-
21
- # As stated in doc, if email and email_hash are both supplied in the same request,
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
- raise ArgumentError, "Either email or email_hash needs to be provided" if email.nil? && email_hash.nil?
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.get("token/validate", params.merge(token: token)).body
29
+ http.post("token/validate", params.merge(token: token)).body
41
30
  end
42
31
 
43
- def refresh_token(refresh_token:)
44
- http.get("token/refresh", { refresh_token: refresh_token }).body
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.get("identity/buckets", since_timestamp: since.utc.iso8601[0..-2]).body
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
- raise ArgumentError, "Either email or email_hash needs to be provided" if email.nil? && email_hash.nil?
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
- @http ||= Faraday.new(
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Uid2
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/uid2.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "uid2/version"
4
+
5
+ require_relative "faraday/uid2"
4
6
  require_relative "uid2/client"
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 = "uid2"
7
- spec.version = Uid2::VERSION
8
- spec.authors = ["Richard Lee"]
9
- spec.email = ["14349+dlackty@users.noreply.github.com"]
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 = "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"
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.1.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: 2021-05-07 00:00:00.000000000 Z
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.4
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