noyo 0.1.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 +7 -0
- data/.circleci/config.yml +57 -0
- data/.codecov.yml +13 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +73 -0
- data/.ruby-version +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +89 -0
- data/README.md +176 -0
- data/Rakefile +6 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/lib/noyo.rb +3 -0
- data/lib/noyo_accounts.rb +4 -0
- data/lib/noyo_accounts/client.rb +6 -0
- data/lib/noyo_accounts/client/services.rb +8 -0
- data/lib/noyo_accounts/client/services/auth_service.rb +45 -0
- data/lib/noyo_api.rb +6 -0
- data/lib/noyo_api/api.rb +13 -0
- data/lib/noyo_api/client.rb +9 -0
- data/lib/noyo_api/client/services.rb +8 -0
- data/lib/noyo_api/client/services/base_service.rb +37 -0
- data/lib/noyo_api/client/user_agent.rb +15 -0
- data/lib/noyo_api/client/version.rb +5 -0
- data/lib/noyo_api/configuration.rb +28 -0
- data/lib/noyo_fulfillment.rb +5 -0
- data/lib/noyo_fulfillment/api_response.rb +32 -0
- data/lib/noyo_fulfillment/models.rb +25 -0
- data/lib/noyo_fulfillment/models/api_resource.rb +191 -0
- data/lib/noyo_fulfillment/models/api_resource_collection.rb +41 -0
- data/lib/noyo_fulfillment/models/base_model.rb +115 -0
- data/lib/noyo_fulfillment/models/contact.rb +19 -0
- data/lib/noyo_fulfillment/models/demographic_change.rb +8 -0
- data/lib/noyo_fulfillment/models/dependent.rb +15 -0
- data/lib/noyo_fulfillment/models/employee.rb +108 -0
- data/lib/noyo_fulfillment/models/group.rb +25 -0
- data/lib/noyo_fulfillment/models/group_enrollment.rb +20 -0
- data/lib/noyo_fulfillment/models/group_plans.rb +15 -0
- data/lib/noyo_fulfillment/models/group_plans/add.rb +11 -0
- data/lib/noyo_fulfillment/models/group_plans/base.rb +22 -0
- data/lib/noyo_fulfillment/models/group_plans/dental.rb +13 -0
- data/lib/noyo_fulfillment/models/group_plans/life.rb +11 -0
- data/lib/noyo_fulfillment/models/group_plans/long_term_disability.rb +11 -0
- data/lib/noyo_fulfillment/models/group_plans/medical.rb +12 -0
- data/lib/noyo_fulfillment/models/group_plans/short_term_disability.rb +11 -0
- data/lib/noyo_fulfillment/models/group_plans/vision.rb +11 -0
- data/lib/noyo_fulfillment/models/individual_enrollment.rb +32 -0
- data/lib/noyo_fulfillment/models/location.rb +16 -0
- data/lib/noyo_fulfillment/models/member_request.rb +40 -0
- data/lib/noyo_fulfillment/models/member_transaction.rb +27 -0
- data/lib/noyo_fulfillment/models/mixins.rb +9 -0
- data/lib/noyo_fulfillment/models/mixins/has_person.rb +29 -0
- data/lib/noyo_fulfillment/models/mixins/nested_under.rb +64 -0
- data/lib/noyo_fulfillment/models/new_hire.rb +7 -0
- data/lib/noyo_fulfillment/models/open_enrollment.rb +7 -0
- data/lib/noyo_fulfillment/models/person.rb +18 -0
- data/lib/noyo_fulfillment/models/qualifying_life_event.rb +8 -0
- data/lib/noyo_fulfillment/models/termination.rb +9 -0
- data/noyo.gemspec +47 -0
- metadata +232 -0
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
data/lib/noyo.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module NoyoAccounts
|
4
|
+
module Client
|
5
|
+
module Services
|
6
|
+
class AuthService < NoyoApi::Client::Services::BaseService
|
7
|
+
include HTTParty
|
8
|
+
include NoyoApi::Client::UserAgent
|
9
|
+
base_uri NoyoApi::Api.config.accounts_base_uri
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
# Get the latest config value, in case it changed
|
13
|
+
self.class.base_uri(NoyoApi::Api.config.accounts_base_uri)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.authorize_path
|
17
|
+
'/auth/public/token'
|
18
|
+
end
|
19
|
+
|
20
|
+
def authorize(client_id, client_secret)
|
21
|
+
auth = {
|
22
|
+
username: client_id,
|
23
|
+
password: client_secret,
|
24
|
+
}
|
25
|
+
body = {
|
26
|
+
grant_type: 'client_credentials',
|
27
|
+
}
|
28
|
+
options = {
|
29
|
+
body: body.to_json,
|
30
|
+
basic_auth: auth,
|
31
|
+
headers: {
|
32
|
+
'Content-Type' => 'application/json',
|
33
|
+
'Accept' => 'application/json',
|
34
|
+
'User-Agent' => self.class.user_agent,
|
35
|
+
},
|
36
|
+
}
|
37
|
+
result = self.class.post(self.class.authorize_path, options)
|
38
|
+
raise 'Bad credentials.' if result.code == 401
|
39
|
+
|
40
|
+
parse_httparty_response(result)&.[]('access_token')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/noyo_api.rb
ADDED
data/lib/noyo_api/api.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module NoyoApi
|
2
|
+
module Client
|
3
|
+
module Services
|
4
|
+
class BaseService
|
5
|
+
def self.root_path
|
6
|
+
'/api/v1'
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.resource
|
10
|
+
class_name = name.split('::').last
|
11
|
+
class_name.gsub(/(.*)(Service)/, '\\1').downcase
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.resource_path
|
15
|
+
File.join(root_path, resource)
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def headers(*_args)
|
21
|
+
{
|
22
|
+
'Content-Type' => 'application/json',
|
23
|
+
'Accept' => 'application/json',
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_httparty_response(httparty_response)
|
28
|
+
response = httparty_response.parsed_response
|
29
|
+
if response.is_a? String
|
30
|
+
response = JSON.parse(response).with_indifferent_access
|
31
|
+
end
|
32
|
+
response
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module NoyoApi
|
2
|
+
class Configuration
|
3
|
+
CONFIG_SETTERS = [
|
4
|
+
:client_id, :client_secret, :access_token, :accounts_base_uri, :fulfillment_base_uri,
|
5
|
+
:verbose,
|
6
|
+
].freeze
|
7
|
+
REQUIRED_SETTERS = [ :client_id, :client_secret ].freeze
|
8
|
+
attr_accessor(*CONFIG_SETTERS)
|
9
|
+
|
10
|
+
def accounts_base_uri
|
11
|
+
@accounts_base_uri || 'https://accounts.development.noyoconnect.com'
|
12
|
+
end
|
13
|
+
|
14
|
+
def fulfillment_base_uri
|
15
|
+
@fulfillment_base_uri || 'https://fulfillment.development.noyoconnect.com'
|
16
|
+
end
|
17
|
+
|
18
|
+
def unconfigured?
|
19
|
+
unconfigured_setters = REQUIRED_SETTERS.map do |setter|
|
20
|
+
value = send(setter)
|
21
|
+
value.nil? ||
|
22
|
+
(value != true && value != false && (!value.respond_to?(:empty?) || value.empty?))
|
23
|
+
end
|
24
|
+
|
25
|
+
unconfigured_setters.any?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module NoyoFulfillment
|
2
|
+
class ServerError < StandardError
|
3
|
+
def initialize(msg = 'There seems to be a problem server side. Please contact ' \
|
4
|
+
"Noyo at eng-admin@gonoyo.com for a fix for the error at #{Time.now}.")
|
5
|
+
super(msg)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class ApiResponse
|
10
|
+
attr_accessor :meta, :response
|
11
|
+
|
12
|
+
def initialize(response)
|
13
|
+
body = response.parsed_response
|
14
|
+
if body.is_a? String
|
15
|
+
parsed_body = JSON.parse(body)
|
16
|
+
if parsed_body.is_a?(Hash)
|
17
|
+
body = parsed_body.with_indifferent_access
|
18
|
+
elsif parsed_body.is_a?(Array)
|
19
|
+
body = parsed_body.map(&:with_indifferent_access)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
raise ServerError unless body.is_a?(Hash) || body.is_a?(Array)
|
23
|
+
|
24
|
+
if body.is_a?(Hash) && body.key?('meta')
|
25
|
+
@meta = body['meta']
|
26
|
+
@response = body['response']
|
27
|
+
else
|
28
|
+
@response = body
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'noyo_fulfillment/models/mixins'
|
2
|
+
require 'noyo_fulfillment/models/base_model'
|
3
|
+
require 'noyo_fulfillment/models/api_resource'
|
4
|
+
require 'noyo_fulfillment/models/api_resource_collection'
|
5
|
+
require 'noyo_fulfillment/models/person'
|
6
|
+
require 'noyo_fulfillment/models/employee'
|
7
|
+
require 'noyo_fulfillment/models/dependent'
|
8
|
+
require 'noyo_fulfillment/models/group'
|
9
|
+
require 'noyo_fulfillment/models/contact'
|
10
|
+
require 'noyo_fulfillment/models/location'
|
11
|
+
require 'noyo_fulfillment/models/group_enrollment'
|
12
|
+
require 'noyo_fulfillment/models/group_plans'
|
13
|
+
require 'noyo_fulfillment/models/new_hire'
|
14
|
+
require 'noyo_fulfillment/models/termination'
|
15
|
+
require 'noyo_fulfillment/models/demographic_change'
|
16
|
+
require 'noyo_fulfillment/models/open_enrollment'
|
17
|
+
require 'noyo_fulfillment/models/qualifying_life_event'
|
18
|
+
require 'noyo_fulfillment/models/member_request'
|
19
|
+
require 'noyo_fulfillment/models/member_transaction'
|
20
|
+
require 'noyo_fulfillment/models/individual_enrollment'
|
21
|
+
|
22
|
+
module NoyoFulfillment
|
23
|
+
module Models
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
# Used for underscore, pluralize
|
3
|
+
require 'active_support/inflector'
|
4
|
+
|
5
|
+
module NoyoFulfillment
|
6
|
+
class ApiResource < NoyoFulfillment::BaseModel
|
7
|
+
include HTTParty
|
8
|
+
include NoyoApi::Client::UserAgent
|
9
|
+
base_uri NoyoApi::Api.config.fulfillment_base_uri
|
10
|
+
|
11
|
+
@@PAGE_SIZE = 20
|
12
|
+
@@MAX_AUTH_ATTEMPTS = 5
|
13
|
+
|
14
|
+
def initialize(params={})
|
15
|
+
super(params)
|
16
|
+
# Get the latest config value, in case it changed
|
17
|
+
self.class.base_uri(NoyoApi::Api.config.fulfillment_base_uri)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.resource_path_name
|
21
|
+
class_name.underscore.pluralize
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.resource_url(**_)
|
25
|
+
if self == ApiResource
|
26
|
+
message = 'ApiResource is an abstract class. You should perform actions on its subclasses.'
|
27
|
+
raise NotImplementedError, message
|
28
|
+
end
|
29
|
+
"/api/v1/#{resource_path_name}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.single_resource_url(id, **_)
|
33
|
+
"#{resource_url}/#{id}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def single_resource_url
|
37
|
+
self.class.single_resource_url(self&.id)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.perform_request_authenticated(*args)
|
41
|
+
if args.length > 2 && !args[2].nil?
|
42
|
+
options = args[2]
|
43
|
+
else
|
44
|
+
options = {}
|
45
|
+
end
|
46
|
+
recursion_depth = options[:recursion_depth] || 0
|
47
|
+
|
48
|
+
if NoyoApi::Api.config.access_token.nil?
|
49
|
+
authenticate
|
50
|
+
end
|
51
|
+
|
52
|
+
if !NoyoApi::Api.config.access_token.nil?
|
53
|
+
options[:headers] ||= {}
|
54
|
+
options[:headers] = options[:headers].merge(headers)
|
55
|
+
|
56
|
+
if NoyoApi::Api.config.verbose
|
57
|
+
puts "Calling API with action: #{args[0]}"
|
58
|
+
puts "Calling API with URL: #{args[1]}"
|
59
|
+
puts "Calling API with options: #{options.to_json}"
|
60
|
+
end
|
61
|
+
|
62
|
+
response = send(args[0], args[1], options)
|
63
|
+
body = get_body(response)
|
64
|
+
|
65
|
+
case response.code
|
66
|
+
when 401
|
67
|
+
reauthenticated = handle_unauthenticated(body)
|
68
|
+
if reauthenticated
|
69
|
+
recursion_depth += 1
|
70
|
+
if recursion_depth < @@MAX_AUTH_ATTEMPTS
|
71
|
+
options[:recursion_depth] = recursion_depth
|
72
|
+
perform_request_authenticated(args[0], args[1], options)
|
73
|
+
else
|
74
|
+
puts "Couldn't successfully reauthenticate." if NoyoApi::Api.config.verbose
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
when 422
|
79
|
+
if NoyoApi::Api.config.verbose
|
80
|
+
puts "Body of response: #{body}"
|
81
|
+
end
|
82
|
+
response
|
83
|
+
else
|
84
|
+
response
|
85
|
+
end
|
86
|
+
elsif access_token.nil?
|
87
|
+
raise 'Could not log in. Please try again later.'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.get_body(response)
|
92
|
+
if response.nil?
|
93
|
+
return {}
|
94
|
+
end
|
95
|
+
|
96
|
+
body = response.parsed_response
|
97
|
+
if body.is_a? String
|
98
|
+
parsed_body = JSON.parse(body)
|
99
|
+
if parsed_body.is_a?(Hash)
|
100
|
+
body = parsed_body.with_indifferent_access
|
101
|
+
elsif parsed_body.is_a?(Array)
|
102
|
+
body = parsed_body.map(&:with_indifferent_access)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
body
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.headers
|
110
|
+
{
|
111
|
+
'Authorization': "Bearer #{NoyoApi::Api.config.access_token}",
|
112
|
+
'Accept': 'application/json',
|
113
|
+
'Content-Type': 'application/json',
|
114
|
+
'User-Agent' => user_agent,
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.authenticate
|
119
|
+
client_id = NoyoApi::Api.config.client_id
|
120
|
+
client_secret = NoyoApi::Api.config.client_secret
|
121
|
+
service = NoyoAccounts::Client::Services::AuthService.new
|
122
|
+
access_token = service.authorize(client_id, client_secret)
|
123
|
+
NoyoApi::Api.config.access_token = access_token
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.all(**args)
|
127
|
+
page_number = args[:page_number] || 1
|
128
|
+
base_uri(NoyoApi::Api.config.fulfillment_base_uri)
|
129
|
+
|
130
|
+
offset = (page_number - 1) * @@PAGE_SIZE
|
131
|
+
query = { offset: offset, page_size: @@PAGE_SIZE }
|
132
|
+
response = perform_request_authenticated(:get, resource_url(args), query: query)
|
133
|
+
api_response = ApiResponse.new(response)
|
134
|
+
response_body = api_response.response
|
135
|
+
if response_body.empty?
|
136
|
+
nil
|
137
|
+
else
|
138
|
+
if response_body.is_a?(Array)
|
139
|
+
results = response_body.map{ |response_item| new(response_item) }
|
140
|
+
NoyoFulfillment::ApiResourceCollection.new(results, page_number)
|
141
|
+
else
|
142
|
+
new(response_body)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.find(id, **args)
|
148
|
+
self.base_uri(NoyoApi::Api.config.fulfillment_base_uri)
|
149
|
+
|
150
|
+
response = perform_request_authenticated(:get, single_resource_url(id, args))
|
151
|
+
body = get_body(response)
|
152
|
+
|
153
|
+
if body.nil? || body.empty?
|
154
|
+
nil
|
155
|
+
else
|
156
|
+
new(body)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.handle_unauthenticated(body)
|
161
|
+
if body&.[]('code') == 16
|
162
|
+
puts 'Need to reauth' if NoyoApi::Api.config.verbose
|
163
|
+
# returns the access token
|
164
|
+
return authenticate
|
165
|
+
end
|
166
|
+
|
167
|
+
false
|
168
|
+
end
|
169
|
+
|
170
|
+
def create_hash
|
171
|
+
attributes
|
172
|
+
end
|
173
|
+
|
174
|
+
def create
|
175
|
+
options = { body: create_hash.to_json }
|
176
|
+
response = self.class.perform_request_authenticated(:post, create_url, options)
|
177
|
+
body = self.class.get_body(response)
|
178
|
+
update_attrs(self.class.new(body))
|
179
|
+
|
180
|
+
self
|
181
|
+
end
|
182
|
+
|
183
|
+
def resource_url
|
184
|
+
self.class.resource_url
|
185
|
+
end
|
186
|
+
|
187
|
+
def create_url
|
188
|
+
resource_url
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|