urbanairship 9.2.0 → 9.3.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/ci.yaml +3 -0
- data/CHANGELOG +7 -0
- data/README.rst +39 -11
- data/lib/urbanairship/client.rb +20 -3
- data/lib/urbanairship/configuration.rb +3 -2
- data/lib/urbanairship/oauth.rb +129 -0
- data/lib/urbanairship/version.rb +1 -1
- data/lib/urbanairship.rb +1 -0
- data/urbanairship.gemspec +2 -1
- metadata +30 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4eec597e4717d02b44f452c7d1d634402e5957d5fe9df6a9cf052e3bb30d9357
|
|
4
|
+
data.tar.gz: 14be54ad8f59edcaa4ce0bfead99249571aa0f6c81d766956886abe994482a5f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 01f091cd844d9dfc38ea6104d4a37aef5afabff3b7ee5bc9c3fc479c492a8dc15c3dbdf71a675c77c6d4138559cdee206dc505438c2c3dabc2b6e7487287add6
|
|
7
|
+
data.tar.gz: 9f5706357ceec8f731412fa966ec40f75ad07e0dec229e2673e56793ebfe382e6e01791ba3fc6ee3e024bbc410cca22de527f222c50ebdf013aa5488298d7839
|
data/.github/workflows/ci.yaml
CHANGED
|
@@ -17,6 +17,9 @@ jobs:
|
|
|
17
17
|
uses: ruby/setup-ruby@477b21f02be01bcb8030d50f37cfec92bfa615b6
|
|
18
18
|
with:
|
|
19
19
|
ruby-version: ${{ matrix.ruby-version }}
|
|
20
|
+
bundler: none
|
|
21
|
+
- name: Install bundler 2.4
|
|
22
|
+
run: gem install bundler -v 2.4.22
|
|
20
23
|
- name: Install dependencies
|
|
21
24
|
run: bundle install
|
|
22
25
|
- name: Run tests
|
data/CHANGELOG
CHANGED
data/README.rst
CHANGED
|
@@ -66,7 +66,8 @@ In your app initialization, you can do something like the following:
|
|
|
66
66
|
require 'urbanairship'
|
|
67
67
|
|
|
68
68
|
Urbanairship.configure do |config|
|
|
69
|
-
config.server = '
|
|
69
|
+
config.server = 'api.asnapieu.com'
|
|
70
|
+
config.oauth_server = 'oauth2.asnapieu.com'
|
|
70
71
|
config.log_path = '/path/to/your/logfile'
|
|
71
72
|
config.log_level = Logger::WARN
|
|
72
73
|
config.timeout = 60
|
|
@@ -87,10 +88,11 @@ If you want to use a custom logger (e.g Rails.logger), you can do:
|
|
|
87
88
|
Available Configurations
|
|
88
89
|
------------------------
|
|
89
90
|
|
|
90
|
-
- **log_path**: Allows to define the folder where the log file will be created (the default is nil).
|
|
91
|
-
- **log_level**: Allows to define the log level and only messages at that level or higher will be printed (the default is INFO).
|
|
92
|
-
- **server**:
|
|
93
|
-
- **
|
|
91
|
+
- **log_path**: Allows you to define the folder where the log file will be created (the default is nil).
|
|
92
|
+
- **log_level**: Allows you to define the log level and only messages at that level or higher will be printed (the default is INFO).
|
|
93
|
+
- **server**: Allows you to define the Airship server you want to use ("api.asnapieu.com" for EU or "api.asnapius.com" for US)
|
|
94
|
+
- **oauth_server** Allows you to define the Airship Oauth server you want to use ("oauth2.asnapieu.com" for EU or "oauth2.asnapius.com" for US)
|
|
95
|
+
- **timeout**: Allows you to define the request timeout in seconds (the default is 5).
|
|
94
96
|
|
|
95
97
|
|
|
96
98
|
Usage
|
|
@@ -140,7 +142,7 @@ Simple Tag Push
|
|
|
140
142
|
|
|
141
143
|
Specify the Airship server used to make your requests
|
|
142
144
|
-----------------------------------------------------
|
|
143
|
-
By default, the request will be sent to the '
|
|
145
|
+
By default, the request will be sent to the 'api.asnapius.com' server:
|
|
144
146
|
|
|
145
147
|
.. code-block:: ruby
|
|
146
148
|
|
|
@@ -155,11 +157,11 @@ You can change the server globally in the Urbanairship configuration:
|
|
|
155
157
|
require 'urbanairship'
|
|
156
158
|
|
|
157
159
|
Urbanairship.configure do |config|
|
|
158
|
-
config.server = '
|
|
160
|
+
config.server = 'api.asnapieu.com'
|
|
159
161
|
end
|
|
160
162
|
|
|
161
163
|
Urbanairship::Client.new(key:'application_key', secret:'master_secret')
|
|
162
|
-
# request will be sent to the '
|
|
164
|
+
# request will be sent to the 'api.asnapieu.com' server
|
|
163
165
|
|
|
164
166
|
Finally, you can change the targeted server on a request basis:
|
|
165
167
|
|
|
@@ -168,12 +170,12 @@ Finally, you can change the targeted server on a request basis:
|
|
|
168
170
|
require 'urbanairship'
|
|
169
171
|
|
|
170
172
|
Urbanairship.configure do |config|
|
|
171
|
-
config.server = '
|
|
173
|
+
config.server = 'api.asnapieu.com'
|
|
172
174
|
end
|
|
173
175
|
|
|
174
|
-
Urbanairship::Client.new(key:'application_key', secret:'master_secret', server: '
|
|
176
|
+
Urbanairship::Client.new(key:'application_key', secret:'master_secret', server: 'api.asnapius.com')
|
|
175
177
|
# The Urbanairship configuration is overridden by the client and the
|
|
176
|
-
# request will be sent to the '
|
|
178
|
+
# request will be sent to the 'api.asnapius.com' server
|
|
177
179
|
|
|
178
180
|
Using Bearer Token Auth
|
|
179
181
|
-----------------------
|
|
@@ -191,6 +193,32 @@ will use bearer token auth. Bearer token auth is required for some
|
|
|
191
193
|
endpoints, but not supported by others. Please check `the Airship
|
|
192
194
|
docs site <https://docs.airship.com/>`_ to see where it is supported.
|
|
193
195
|
|
|
196
|
+
Using Oauth
|
|
197
|
+
-----------
|
|
198
|
+
.. code-block:: ruby
|
|
199
|
+
|
|
200
|
+
require 'urbanairship'
|
|
201
|
+
|
|
202
|
+
UA = Urbanairship
|
|
203
|
+
app_key = 'application_key'
|
|
204
|
+
|
|
205
|
+
oauth = UA::Oauth.new(
|
|
206
|
+
client_id: 'client_id',
|
|
207
|
+
key: app_key,
|
|
208
|
+
assertion_private_key: 'your_private_key',
|
|
209
|
+
scopes: ['psh', 'chn'], # Optional
|
|
210
|
+
ip_addresses: ['23.74.131.15/22'], # Optional
|
|
211
|
+
oauth_server: 'api.asnapieu.com' # Optional
|
|
212
|
+
)
|
|
213
|
+
airship = UA::Client.new(key: app_key, oauth: oauth)
|
|
214
|
+
# Then continue as you would otherwise
|
|
215
|
+
|
|
216
|
+
**Note**: You can not use both Oauth and bearer token auth
|
|
217
|
+
at the same time. Oauth also cannot be used with the older
|
|
218
|
+
'api.urbanairship.com' and 'api.airship.eu' base URLs. Lastly
|
|
219
|
+
there are some endpoints in which Oauth is not supported.
|
|
220
|
+
Please check `the Airship docs site <https://docs.airship.com/>`_ to see where it is supported.
|
|
221
|
+
|
|
194
222
|
Contributing
|
|
195
223
|
============
|
|
196
224
|
|
data/lib/urbanairship/client.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
require 'json'
|
|
2
2
|
require 'rest-client'
|
|
3
3
|
require 'urbanairship'
|
|
4
|
+
require 'jwt'
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
module Urbanairship
|
|
7
8
|
class Client
|
|
8
|
-
attr_accessor :key, :secret
|
|
9
|
+
attr_accessor :key, :secret, :token
|
|
9
10
|
include Urbanairship::Common
|
|
10
11
|
include Urbanairship::Loggable
|
|
11
12
|
|
|
@@ -13,15 +14,21 @@ module Urbanairship
|
|
|
13
14
|
#
|
|
14
15
|
# @param [Object] key Application Key
|
|
15
16
|
# @param [Object] secret Application Secret
|
|
16
|
-
# @param [String] server Airship server to use ("
|
|
17
|
+
# @param [String] server Airship server to use ("api.asnapieu.com" for EU or "api.asnapius.com" for US).
|
|
17
18
|
# Used only when the request is sent with a "path", not an "url".
|
|
18
19
|
# @param [String] token Application Auth Token
|
|
20
|
+
# @param [Object] oauth Oauth object
|
|
19
21
|
# @return [Object] Client
|
|
20
|
-
def initialize(key: required('key'), secret: nil, server: Urbanairship.configuration.server, token: nil)
|
|
22
|
+
def initialize(key: required('key'), secret: nil, server: Urbanairship.configuration.server, token: nil, oauth: nil)
|
|
21
23
|
@key = key
|
|
22
24
|
@secret = secret
|
|
23
25
|
@server = server
|
|
24
26
|
@token = token
|
|
27
|
+
@oauth = oauth
|
|
28
|
+
|
|
29
|
+
if @oauth != nil && @token != nil
|
|
30
|
+
raise ArgumentError.new("oauth and token can't both be used at the same time.")
|
|
31
|
+
end
|
|
25
32
|
end
|
|
26
33
|
|
|
27
34
|
# Send a request to Airship's API
|
|
@@ -56,6 +63,16 @@ module Urbanairship
|
|
|
56
63
|
headers['Content-Type'] = content_type unless content_type.nil?
|
|
57
64
|
headers['Content-Encoding'] = encoding unless encoding.nil?
|
|
58
65
|
|
|
66
|
+
unless @oauth.nil?
|
|
67
|
+
begin
|
|
68
|
+
@token = @oauth.get_token
|
|
69
|
+
rescue RestClient::Exception => e
|
|
70
|
+
new_error = RestClient::Exception.new(e.response, e.response.code)
|
|
71
|
+
new_error.message = "error while getting oauth token: #{e.message}"
|
|
72
|
+
raise new_error
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
59
76
|
if @token != nil
|
|
60
77
|
auth_type = :bearer
|
|
61
78
|
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
module Urbanairship
|
|
2
2
|
class Configuration
|
|
3
|
-
attr_accessor :custom_logger, :log_path, :log_level, :server, :timeout
|
|
3
|
+
attr_accessor :custom_logger, :log_path, :log_level, :server, :oauth_server, :timeout
|
|
4
4
|
|
|
5
5
|
def initialize
|
|
6
|
-
@server = '
|
|
6
|
+
@server = 'api.asnapius.com'
|
|
7
|
+
@oauth_server = 'oauth2.asnapius.com'
|
|
7
8
|
@custom_logger = nil
|
|
8
9
|
@log_path = nil
|
|
9
10
|
@log_level = Logger::INFO
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
require 'urbanairship'
|
|
2
|
+
require 'base64'
|
|
3
|
+
require 'rest-client'
|
|
4
|
+
|
|
5
|
+
module Urbanairship
|
|
6
|
+
class Oauth
|
|
7
|
+
attr_accessor :client_id, :sub, :assertion_private_key, :ip_addresses, :scopes, :oauth_server
|
|
8
|
+
|
|
9
|
+
# Initialize Oauth class
|
|
10
|
+
#
|
|
11
|
+
# @param [String] client_id The Client ID found when creating Oauth credentials in the dashboard.
|
|
12
|
+
# @param [String] key The app key for the project.
|
|
13
|
+
# @param [String] assertion_private_key The private key found when creating Oauth credentials in the dashboard. Used for assertion token auth.
|
|
14
|
+
# @param [Array<String>] ip_addresses A list of CIDR representations of valid IP addresses to which the issued token is restricted. Example: ['24.20.40.0/22', '34.17.3.0/22']
|
|
15
|
+
# @param [Array<String>] scopes A list of scopes to which the issued token will be entitled. Example: ['psh', 'lst']
|
|
16
|
+
# @param [String] oauth_server The server to send Oauth token requests to. By default is 'oauth2.asnapius.com', but can be set to 'oauth2.asnapieu.com' if using the EU server.
|
|
17
|
+
# @return [Object] Oauth object
|
|
18
|
+
def initialize(client_id:, key:, assertion_private_key:, ip_addresses: [], scopes: [], oauth_server: Urbanairship.configuration.oauth_server)
|
|
19
|
+
@grant_type = 'client_credentials'
|
|
20
|
+
@client_id = client_id
|
|
21
|
+
@assertion_private_key = assertion_private_key
|
|
22
|
+
@ip_addresses = ip_addresses
|
|
23
|
+
@scopes = scopes
|
|
24
|
+
@sub = "app:#{key}"
|
|
25
|
+
@oauth_server = oauth_server
|
|
26
|
+
@token = nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Get an Oauth token from Airship Oauth servers.
|
|
30
|
+
#
|
|
31
|
+
# @return [String] JSON web token to be used in further Airship API requests.
|
|
32
|
+
def get_token
|
|
33
|
+
unless @token.nil?
|
|
34
|
+
decoded_jwt = JWT.decode(@token, nil, false)
|
|
35
|
+
current_time = Time.now.to_i
|
|
36
|
+
expiry_time = decoded_jwt[0]['exp']
|
|
37
|
+
|
|
38
|
+
if current_time < expiry_time
|
|
39
|
+
return @token
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
assertion_jwt = build_assertion_jwt
|
|
44
|
+
|
|
45
|
+
url = "https://#{@oauth_server}/token"
|
|
46
|
+
headers = {
|
|
47
|
+
'Host': @oauth_server,
|
|
48
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
49
|
+
'Accept': 'application/json'
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
params = {
|
|
53
|
+
method: :post,
|
|
54
|
+
url: url,
|
|
55
|
+
headers: headers,
|
|
56
|
+
payload: {
|
|
57
|
+
grant_type: @grant_type,
|
|
58
|
+
assertion: assertion_jwt
|
|
59
|
+
},
|
|
60
|
+
timeout: 60
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
retries = 0
|
|
64
|
+
max_retries = 3
|
|
65
|
+
begin
|
|
66
|
+
response = RestClient::Request.execute(params)
|
|
67
|
+
@token = JSON.parse(response.body)['access_token']
|
|
68
|
+
return @token
|
|
69
|
+
rescue RestClient::ExceptionWithResponse => e
|
|
70
|
+
if [400, 401, 406].include?(e.response.code)
|
|
71
|
+
raise e
|
|
72
|
+
else
|
|
73
|
+
retries += 1
|
|
74
|
+
if retries <= max_retries
|
|
75
|
+
sleep(retries ** 2)
|
|
76
|
+
retry
|
|
77
|
+
else
|
|
78
|
+
new_error = RestClient::Exception.new(e.response, e.response.code)
|
|
79
|
+
new_error.message = "failed after 3 attempts with error: #{e}"
|
|
80
|
+
raise new_error
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Build an assertion JWT
|
|
87
|
+
#
|
|
88
|
+
# @return [String] Assertion JWT to be used when requesting an Oauth token from Airship servers.
|
|
89
|
+
def build_assertion_jwt
|
|
90
|
+
assertion_expiration = 61
|
|
91
|
+
private_key = OpenSSL::PKey::EC.new(@assertion_private_key)
|
|
92
|
+
|
|
93
|
+
headers = {
|
|
94
|
+
alg: 'ES384',
|
|
95
|
+
kid: @client_id
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
claims = {
|
|
99
|
+
aud: "https://#{@oauth_server}/token",
|
|
100
|
+
exp: Time.now.to_i + assertion_expiration,
|
|
101
|
+
iat: Time.now.to_i,
|
|
102
|
+
iss: @client_id,
|
|
103
|
+
nonce: SecureRandom.uuid,
|
|
104
|
+
sub: @sub
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
claims[:scope] = @scopes.join(' ') if @scopes.any?
|
|
108
|
+
claims[:ipaddr] = @ip_addresses.join(' ') if @ip_addresses.any?
|
|
109
|
+
|
|
110
|
+
JWT.encode(claims, private_key, 'ES384', headers)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Verify a public key
|
|
114
|
+
#
|
|
115
|
+
# @param [String] key_id The key ID ('kid') found in the header when decoding an Oauth token granted from Airship's servers.
|
|
116
|
+
# @return [String] The public key associated with the Key ID.
|
|
117
|
+
def verify_public_key(key_id)
|
|
118
|
+
url = "https://#{@oauth_server}/verify/public_key/#{key_id}"
|
|
119
|
+
|
|
120
|
+
headers = {
|
|
121
|
+
'Host': @oauth_server,
|
|
122
|
+
'Accept': 'text/plain'
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
response = RestClient.get(url, headers)
|
|
126
|
+
response.body
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
data/lib/urbanairship/version.rb
CHANGED
data/lib/urbanairship.rb
CHANGED
|
@@ -15,6 +15,7 @@ require 'urbanairship/devices/create_and_send'
|
|
|
15
15
|
require 'urbanairship/devices/attribute'
|
|
16
16
|
require 'urbanairship/devices/attributes'
|
|
17
17
|
require 'urbanairship/client'
|
|
18
|
+
require 'urbanairship/oauth'
|
|
18
19
|
require 'urbanairship/common'
|
|
19
20
|
require 'urbanairship/configuration'
|
|
20
21
|
require 'urbanairship/loggable'
|
data/urbanairship.gemspec
CHANGED
|
@@ -28,8 +28,9 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
spec.require_paths = ['lib']
|
|
29
29
|
|
|
30
30
|
spec.add_runtime_dependency 'rest-client', '>= 1.4', '< 4.0'
|
|
31
|
+
spec.add_runtime_dependency 'jwt', '>= 2.0', '< 3.0'
|
|
31
32
|
|
|
32
|
-
spec.add_development_dependency 'bundler', '>= 1'
|
|
33
|
+
spec.add_development_dependency 'bundler', '>= 1', '< 2.5'
|
|
33
34
|
spec.add_development_dependency 'guard-rspec'
|
|
34
35
|
spec.add_development_dependency 'pry', '~> 0'
|
|
35
36
|
spec.add_development_dependency 'rake', '~> 12.3.3'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: urbanairship
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 9.
|
|
4
|
+
version: 9.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Airship
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-05-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rest-client
|
|
@@ -30,6 +30,26 @@ dependencies:
|
|
|
30
30
|
- - "<"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
32
|
version: '4.0'
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: jwt
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '2.0'
|
|
40
|
+
- - "<"
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: '3.0'
|
|
43
|
+
type: :runtime
|
|
44
|
+
prerelease: false
|
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '2.0'
|
|
50
|
+
- - "<"
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '3.0'
|
|
33
53
|
- !ruby/object:Gem::Dependency
|
|
34
54
|
name: bundler
|
|
35
55
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -37,6 +57,9 @@ dependencies:
|
|
|
37
57
|
- - ">="
|
|
38
58
|
- !ruby/object:Gem::Version
|
|
39
59
|
version: '1'
|
|
60
|
+
- - "<"
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '2.5'
|
|
40
63
|
type: :development
|
|
41
64
|
prerelease: false
|
|
42
65
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -44,6 +67,9 @@ dependencies:
|
|
|
44
67
|
- - ">="
|
|
45
68
|
- !ruby/object:Gem::Version
|
|
46
69
|
version: '1'
|
|
70
|
+
- - "<"
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '2.5'
|
|
47
73
|
- !ruby/object:Gem::Dependency
|
|
48
74
|
name: guard-rspec
|
|
49
75
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -202,6 +228,7 @@ files:
|
|
|
202
228
|
- lib/urbanairship/devices/static_lists.rb
|
|
203
229
|
- lib/urbanairship/devices/tag_lists.rb
|
|
204
230
|
- lib/urbanairship/loggable.rb
|
|
231
|
+
- lib/urbanairship/oauth.rb
|
|
205
232
|
- lib/urbanairship/push/audience.rb
|
|
206
233
|
- lib/urbanairship/push/payload.rb
|
|
207
234
|
- lib/urbanairship/push/push.rb
|
|
@@ -230,7 +257,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
230
257
|
- !ruby/object:Gem::Version
|
|
231
258
|
version: '0'
|
|
232
259
|
requirements: []
|
|
233
|
-
rubygems_version: 3.
|
|
260
|
+
rubygems_version: 3.1.6
|
|
234
261
|
signing_key:
|
|
235
262
|
specification_version: 4
|
|
236
263
|
summary: Ruby Gem for using the Airship API
|