plaid 1.4.3 → 1.5.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.
@@ -1,173 +0,0 @@
1
- require_relative 'account/account'
2
- require_relative 'transaction/transaction'
3
- require_relative 'info/info'
4
- require 'plaid/util'
5
- require 'json'
6
- module Plaid
7
- class Plaid::User
8
- include Plaid::Util
9
-
10
- # Define user vars
11
- attr_accessor(:accounts, :transactions, :access_token, :type, :permissions, :api_res, :pending_mfa_questions, :info, :information)
12
-
13
- def initialize
14
- self.accounts = [], self.transactions = [], self.permissions = [], self.access_token = '', self.api_res = '', self.info = {}, self.information = Information.new
15
- end
16
-
17
- # Instantiate a new user with the results of the successful API call
18
- # Build an array of nested accounts, and return self if successful
19
- def new(res,api_level=nil)
20
- build_user(res,api_level)
21
- end
22
-
23
- def mfa_authentication(auth,type=nil)
24
- type = self.type if type.nil?
25
- auth_path = self.permissions.last + '/step'
26
- res = Plaid.post(auth_path,{mfa:auth,access_token:self.access_token,type:type})
27
- self.accounts = [], self.transactions = []
28
- build_user(res)
29
- end
30
-
31
- def select_mfa_method(selection,type=nil)
32
- type = self.type if type.nil?
33
- auth_path = self.permissions.last + '/step'
34
- res = Plaid.post(auth_path,{options:{send_method: selection}.to_json, access_token:self.access_token,type:type})
35
- build_user(res,self.permissions.last)
36
- end
37
-
38
- def get_auth
39
- if self.permissions.include? 'auth'
40
- res = Plaid.post('auth/get',{access_token:self.access_token})
41
- build_user(res)
42
- else
43
- false
44
- end
45
- end
46
-
47
- def get_connect(options=nil)
48
- if self.permissions.include? 'connect'
49
- payload = {access_token:self.access_token}
50
- payload.merge!(options) if options
51
- res = Plaid.post('connect/get',payload)
52
- build_user(res)
53
- else
54
- false
55
- end
56
- end
57
-
58
- def get_info
59
- if self.permissions.include? 'info'
60
- res = Plaid.secure_get('info',self.access_token)
61
- build_user(res)
62
- else
63
- false
64
- end
65
- end
66
-
67
- def update_info(username,pass,pin=nil)
68
- if self.permissions.include? 'info'
69
- payload = {username:username,password:pass,access_token:self.access_token}
70
- payload.merge!({pin:pin}) if pin
71
- res = Plaid.patch('info',payload)
72
- puts res
73
- build_user(res)
74
- else
75
- false
76
- end
77
- end
78
-
79
- def update_balance
80
- res = Plaid.post('balance',{access_token:self.access_token})
81
- build_user(res)
82
- end
83
-
84
- def upgrade(api_level=nil)
85
- if api_level.nil?
86
- api_level = 'auth' unless self.permissions.include? 'auth'
87
- api_level = 'connect' unless self.permissions.include? 'connect'
88
- end
89
- res = Plaid.post('upgrade',{access_token:self.access_token,upgrade_to:api_level})
90
- self.accounts = [], self.transactions = []
91
- build_user(res)
92
- end
93
-
94
- def delete_user
95
- Plaid.delete('info',{access_token:self.access_token})
96
- end
97
-
98
- protected
99
-
100
- def build_user(res,api_level=nil)
101
- begin
102
- if res[:msg].nil?
103
- populate_user(self,res,api_level)
104
- clean_up_user(self)
105
- else
106
- set_mfa_request(self,res,api_level)
107
- end
108
- rescue => e
109
- error_handler(e)
110
- else
111
- self
112
- end
113
- end
114
-
115
- # Instantiate and build a new account object, return this to the accounts array
116
- def new_account(res)
117
- account = Account.new
118
- account.new(res)
119
- end
120
-
121
- # Instantiate and build a new account object, return this to the accounts array
122
- def new_transaction(res)
123
- transaction = Transaction.new
124
- transaction.new(res)
125
- end
126
-
127
- private
128
-
129
- def clean_up_user(user)
130
- user.accounts.reject! { |c| !c.instance_of? Plaid::Account }
131
- user
132
- end
133
-
134
- def set_mfa_request(user,res,api_level)
135
- user.access_token = res[:body]['access_token']
136
- user.pending_mfa_questions = res[:body]
137
- user.api_res = res[:msg]
138
- user.permissions << api_level unless self.permissions.include? api_level && api_level.nil?
139
- end
140
-
141
- def populate_user(user,res,api_level)
142
- res['accounts'].each do |account|
143
- if user.accounts.any? { |h| h == account['_id'] }
144
- owned_account = user.accounts.find { |h| h == account['_id'] }
145
- owned_account.new(account)
146
- else
147
- user.accounts << new_account(account)
148
- end
149
- end if res['accounts']
150
-
151
- res['transactions'].each do |transaction|
152
- if user.transactions.any? { |t| t == transaction['_id'] }
153
- owned_transaction = user.transactions.find { |h| h == transaction['_id'] }
154
- owned_transaction.new(transaction)
155
- else
156
- user.transactions << new_transaction(transaction)
157
- end
158
- end if res['transactions']
159
-
160
- user.permissions << api_level unless user.permissions.include? api_level && api_level.nil?
161
- user.pending_mfa_questions = ''
162
- user.information.update_info(res['info']) if res['info']
163
- user.api_res = 'success'
164
-
165
- # TODO: Remove the following line when upgrading to V-2
166
- user.info.merge!(res['info']) if res['info']
167
- # End TODO
168
- user.access_token = res['access_token'].split[0]
169
- user.type = res['access_token'].split[1]
170
- end
171
-
172
- end
173
- end
data/lib/plaid/util.rb DELETED
@@ -1,120 +0,0 @@
1
- require 'net/http'
2
- require 'json'
3
- require 'uri'
4
- module Plaid
5
- module Util
6
-
7
- def post(path,options={})
8
- uri = build_uri(path)
9
- options.merge!({client_id: self.instance_variable_get(:'@customer_id') ,secret: self.instance_variable_get(:'@secret')})
10
- res = Net::HTTP.post_form(uri,options)
11
- parse_response(res)
12
- end
13
-
14
- def get(path,id=nil)
15
- uri = build_uri(path,id)
16
- res = Net::HTTP.get(uri)
17
- parse_get_response(res)
18
- end
19
-
20
- def secure_get(path,access_token,options={})
21
- uri = build_uri(path)
22
- options.merge!({access_token:access_token})
23
- req = Net::HTTP::Get.new(uri)
24
- req.body = URI.encode_www_form(options) if options
25
- req.content_type = 'multipart/form-data'
26
- res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') { |http| http.request(req) }
27
- parse_response(res)
28
- end
29
-
30
- def patch(path,options={})
31
- uri = build_uri(path)
32
- options.merge!({client_id: self.instance_variable_get(:'@customer_id') ,secret: self.instance_variable_get(:'@secret')})
33
- req = Net::HTTP::Patch.new(uri)
34
- req.body = URI.encode_www_form(options) if options
35
- req.content_type = 'multipart/form-data'
36
- res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') { |http| http.request(req) }
37
- parse_response(res)
38
- end
39
-
40
- def delete(path,options={})
41
- uri = build_uri(path)
42
- options.merge!({client_id: self.instance_variable_get(:'@customer_id') ,secret: self.instance_variable_get(:'@secret')})
43
- req = Net::HTTP::Delete.new(uri)
44
- req.body = URI.encode_www_form(options) if options
45
- req.content_type = 'multipart/form-data'
46
- Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') { |http| http.request(req) }
47
- end
48
-
49
- def error_handler(err,res=nil)
50
- case err
51
- when 'Bad Request'
52
- puts res.body
53
- raise 'The request was malformed. Did you check the API docs?'
54
- when 'Unauthorized'
55
- raise 'Access denied: Try using the correct credentials.'
56
- when 'Request Failed'
57
- raise 'Request Failed'
58
- when 'Not Found'
59
- raise 'Not Found'
60
- when 'Institution not supported'
61
- raise 'Institution not supported'
62
- when 'Corrupted token'
63
- raise 'It appears that the access token has been corrupted'
64
- else
65
- raise err
66
- end
67
- end
68
-
69
- protected
70
-
71
- def build_uri(path,option=nil)
72
- path = path + '/' + option unless option.nil?
73
- URI.parse(self.instance_variable_get(:'@environment_location') + path)
74
- end
75
-
76
- private
77
-
78
- def parse_response(res)
79
- body = JSON.parse(res.body)
80
- case res.code.delete('.').to_i
81
- when 200
82
- return body
83
- when 201
84
- return { msg: 'Requires further authentication', body: body}
85
- when 400
86
- error_handler('Bad Request',res)
87
- when 401
88
- error_handler('Institution not supported',res) if body['code'] == 1108
89
- error_handler('Corrupted token',res) if body['code'] == 1105
90
- error_handler('Not Found',res) if body['code'] == 1501
91
- error_handler('Unauthorized',res)
92
- when 402
93
- return {msg: 'User account is locked', body: body} if body['code'] == 1205
94
- error_handler('Request Failed', res)
95
- when 404
96
- error_handler('Not Found',res)
97
- else
98
- error_handler('Server Error',res)
99
- end
100
- end
101
-
102
- def parse_get_response(res)
103
- body = JSON.parse(res)
104
- if body.class == Array
105
- body
106
- else
107
- if body['code'].nil?
108
- body
109
- else
110
- if body['code'] == 1301 || body['code'] == 1401 || body['code'] == 1501 || body['code'] == 1601
111
- error_handler('Not Found',body)
112
- else
113
- body
114
- end
115
- end
116
- end
117
- end
118
-
119
- end
120
- end
@@ -1,113 +0,0 @@
1
- require 'spec_helper.rb'
2
- # Authentication flow specs - returns Plaid::User
3
- describe '.add_user' do
4
-
5
- Plaid.config do |p|
6
- p.customer_id = 'test_id'
7
- p.secret = 'test_secret'
8
- p.environment_location = 'https://tartan.plaid.com/'
9
- end
10
-
11
- context 'has correct credentials for single factor auth, authenticates to the connect level of api access' do
12
- user = Plaid.add_user('connect','plaid_test','plaid_good','wells')
13
- it { expect(user.accounts.empty?).to be_falsey }
14
- end
15
-
16
- context 'has correct credentials for single factor auth, authenticates to the auth level of api access' do
17
- user = Plaid.add_user('auth','plaid_test','plaid_good','wells')
18
- it { expect(user.accounts[0].numbers.nil?).to be_falsey }
19
- end
20
-
21
- context 'has correct credentials for single factor auth, authenticates to the info level of api access' do
22
- user = Plaid.add_user('info','plaid_test','plaid_good','wells')
23
- it { expect(user.info).to be_truthy }
24
- end
25
-
26
- context 'has correct username, but incorrect password for single factor auth under auth level of api access' do
27
- it { expect{Plaid.add_user('auth','plaid_test','plaid_bad','wells')}.to raise_error }
28
- end
29
-
30
- context 'has incorrect username under auth level of api access' do
31
- it { expect{Plaid.add_user('auth','plaid_bad','plaid_bad','wells')}.to raise_error }
32
- end
33
-
34
- context 'has correct username, but incorrect password for single factor auth under connect level of api access' do
35
- it { expect{Plaid.add_user('connect','plaid_test','plaid_bad','wells')}.to raise_error }
36
- end
37
-
38
- context 'has incorrect username under connect level of api access' do
39
- it { expect{Plaid.add_user('connect','plaid_bad','plaid_bad','wells')}.to raise_error }
40
- end
41
-
42
- context 'has correct username, but incorrect password for single factor auth under info level of api access' do
43
- it { expect{Plaid.add_user('info','plaid_test','plaid_bad','wells')}.to raise_error }
44
- end
45
-
46
- context 'has incorrect username under info level of api access' do
47
- it { expect{Plaid.add_user('info','plaid_bad','plaid_bad','wells')}.to raise_error }
48
- end
49
-
50
- context 'enters pin for extra parameter authentication required by certain institutions' do
51
- user = Plaid.add_user('connect','plaid_test','plaid_good','usaa','1234')
52
- it { expect(user.api_res).to eq 'Requires further authentication' }
53
- end
54
-
55
- context 'enters incorrect pin for extra parameter authentication required by certain institutions' do
56
- it { expect{Plaid.add_user('connect','plaid_test','plaid_good','usaa','0000')}.to raise_error }
57
- end
58
-
59
- context 'has to enter MFA credentials' do
60
- user = Plaid.add_user('connect','plaid_test', 'plaid_good','bofa')
61
- it { expect(user.api_res).to eq 'Requires further authentication' }
62
- end
63
-
64
- context 'enters correct information with locked account' do
65
- user = Plaid.add_user('connect','plaid_test', 'plaid_locked','wells')
66
- it { expect(user.api_res).to eq 'User account is locked' }
67
- end
68
-
69
- context 'enters webhook option as part of standard call' do
70
- user = Plaid.add_user('connect','plaid_test', 'plaid_good','wells',{login_only: true, webhook: 'test.com/test.endpoint.aspx'})
71
- it { expect(user.accounts.empty?).to be_falsey }
72
- end
73
-
74
- context 'enters webhook option as part of mfa required institution authentication' do
75
- user = Plaid.add_user('connect','plaid_test', 'plaid_good','bofa',{login_only: true, webhook: 'test.com/test.endpoint.aspx'})
76
- it { expect(user.api_res).to eq 'Requires further authentication' }
77
- end
78
-
79
- context 'requests pending transactions from an institution' do
80
- user = Plaid.add_user('connect','plaid_test', 'plaid_good','wells',{pending: true})
81
- it { expect(user.accounts.empty?).to be_falsey }
82
- end
83
-
84
- context 'sets the login only option to true' do
85
- user = Plaid.add_user('connect','plaid_test', 'plaid_good','wells',{login_only:true})
86
- it { expect(user.accounts.empty?).to be_falsey }
87
- end
88
-
89
- context 'requests a list of options for code based MFA' do
90
- user = Plaid.add_user('connect','plaid_test', 'plaid_good','citi',{list: true})
91
- it { expect(user.pending_mfa_questions.nil?).to be_falsey }
92
- end
93
-
94
- context 'sets a start date for transactions' do
95
- user = Plaid.add_user('connect','plaid_test', 'plaid_good','wells',{login_only:true, start_date:'10 days ago'})
96
- it { expect(user.accounts.empty?).to be_falsey }
97
- end
98
-
99
- context 'sets an end date for transactions' do
100
- user = Plaid.add_user('connect','plaid_test', 'plaid_good','wells',{login_only:true, end_date: '10 days ago'})
101
- it { expect(user.accounts.empty?).to be_falsey }
102
- end
103
-
104
- context 'sets start and end dates for transactions' do
105
- user = Plaid.add_user('connect','plaid_test','plaid_good','wells',"{'gte':'05/10/2014' , 'lte':'06/10/2014'}")
106
- it{ expect(user.transactions).to be_truthy }
107
- end
108
-
109
- context 'sets a user with an existing access token' do
110
- user = Plaid.set_user('test')
111
- it{ expect(user.access_token).to eq('test')}
112
- end
113
- end