authy 2.7.5 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,11 +6,9 @@ require 'json'
6
6
 
7
7
  require 'authy/version'
8
8
  require 'authy/url_helpers'
9
- require 'authy/core_ext'
10
9
  require 'authy/response'
11
10
  require 'authy/models/user'
12
11
  require 'authy/config'
13
12
  require 'authy/api'
14
- require 'authy/phone_intelligence'
15
13
  require 'authy/phone_verification'
16
14
  require 'authy/onetouch'
@@ -1,12 +1,6 @@
1
- require 'logger'
1
+ require "logger"
2
2
 
3
3
  module Authy
4
-
5
- AUTHY_LOGGER = Logger.new(STDOUT)
6
- #
7
- # Authy.api_key = 'foo'
8
- # Authy.api_uri = 'http://test-authy-api.heroku.com/'
9
- #
10
4
  class API
11
5
  MIN_TOKEN_SIZE = 6
12
6
  MAX_TOKEN_SIZE = 12
@@ -25,7 +19,7 @@ module Authy
25
19
  }
26
20
 
27
21
  url = "#{Authy.api_uri}/protected/json/users/new"
28
- response = http_client.post(url, :body => escape_query(params), :header => default_header(api_key: api_key))
22
+ response = http_client.post(url, :body => escape_query(params), :header => default_header(params: { api_key: api_key }))
29
23
 
30
24
  Authy::User.new(response)
31
25
  end
@@ -36,19 +30,18 @@ module Authy
36
30
  # :force (true|false) force to check even if the cellphone is not confirmed
37
31
  #
38
32
  def self.verify(params)
39
- token = params.delete(:token) || params.delete('token')
40
- user_id = params.delete(:id) || params.delete('id')
33
+ token = params.delete(:token) || params.delete("token")
34
+ user_id = params.delete(:id) || params.delete("id")
41
35
 
42
- return invalid_response('Token format is invalid') unless token_is_safe?(token)
43
- return invalid_response('User id is invalid') unless is_digit?(user_id)
36
+ return invalid_response("Token format is invalid") unless token_is_safe?(token)
37
+ return invalid_response("User id is invalid") unless is_digit?(user_id)
44
38
 
45
- params[:force] = true if params[:force].nil? && params['force'].nil?
39
+ params[:force] = true if params[:force].nil? && params["force"].nil?
46
40
 
47
41
  response = get_request("protected/json/verify/:token/:user_id", params.merge({
48
- "token" => token,
49
- "user_id" => user_id
50
- })
51
- )
42
+ "token" => token,
43
+ "user_id" => user_id
44
+ }))
52
45
 
53
46
  return verify_response(response) if response.ok?
54
47
  return response
@@ -58,7 +51,7 @@ module Authy
58
51
  # :id user id
59
52
  # :force force sms
60
53
  def self.request_sms(params)
61
- user_id = params.delete(:id) || params.delete('id')
54
+ user_id = params.delete(:id) || params.delete("id")
62
55
 
63
56
  get_request("protected/json/sms/:user_id", params.merge({"user_id" => user_id}))
64
57
  end
@@ -68,14 +61,14 @@ module Authy
68
61
  # :qr_size qr size
69
62
  # :qr_label context for qr code
70
63
  def self.request_qr_code(params)
71
- user_id = params.delete(:id) || params.delete('id')
72
- qr_size = params.delete(:qr_size) || params.delete('qr_size') || 300
73
- qr_label = params.delete(:qr_label) || params.delete('qr_label') || ""
64
+ user_id = params.delete(:id) || params.delete("id")
65
+ qr_size = params.delete(:qr_size) || params.delete("qr_size") || 300
66
+ qr_label = params.delete(:qr_label) || params.delete("qr_label") || ""
74
67
 
75
- return invalid_response('User id is invalid') unless is_digit?(user_id)
76
- return invalid_response('Qr image size is invalid') unless is_digit?(qr_size)
68
+ return invalid_response("User id is invalid") unless is_digit?(user_id)
69
+ return invalid_response("Qr image size is invalid") unless is_digit?(qr_size)
77
70
 
78
- response = post_request("protected/json/users/:user_id/secret" ,params.merge({
71
+ response = post_request("protected/json/users/:user_id/secret", params.merge({
79
72
  "user_id" => user_id,
80
73
  "qr_size" => qr_size,
81
74
  "label" => qr_label
@@ -86,19 +79,38 @@ module Authy
86
79
  # :id user id
87
80
  # :force force phone_call
88
81
  def self.request_phone_call(params)
89
- user_id = params.delete(:id) || params.delete('id')
82
+ user_id = params.delete(:id) || params.delete("id")
90
83
 
91
84
  get_request("protected/json/call/:user_id", params.merge({"user_id" => user_id}))
92
85
  end
93
86
 
94
87
  # options:
95
88
  # :id user id
96
- def self.delete_user(params)
89
+ def self.request_email(params)
90
+ user_id = params.delete(:id) || params.delete('id')
91
+
92
+ post_request("protected/json/email/:user_id", params.merge({"user_id" => user_id}))
93
+ end
94
+
95
+ # options:
96
+ # :id user id
97
+ # :email user's new email
98
+ def self.update_user(params)
97
99
  user_id = params.delete(:id) || params.delete('id')
98
100
 
99
- post_request("protected/json/users/delete/:user_id", params.merge({"user_id" =>user_id}))
101
+ post_request("protected/json/users/:user_id/update", params.merge({"user_id" => user_id}))
100
102
  end
101
103
 
104
+ # options:
105
+ # :id user id
106
+ def self.delete_user(params)
107
+ user_id = params.delete(:id) || params.delete("id")
108
+
109
+ post_request("protected/json/users/delete/:user_id", params.merge({"user_id" => user_id}))
110
+ end
111
+
112
+ # options:
113
+ # :id user id
102
114
  def self.user_status(params)
103
115
  user_id = params.delete(:id) || params.delete("id")
104
116
  get_request("protected/json/users/:user_id/status", params.merge({"user_id" => user_id}))
@@ -113,12 +125,12 @@ module Authy
113
125
  state, error = validate_for_url(uri_params, params)
114
126
 
115
127
  response = if state
116
- url = "#{Authy.api_uri}/#{eval_uri(uri, params)}"
117
- params = clean_uri_params(uri_params, params)
118
- http_client.post(url, :body => escape_query(params), header: header_)
119
- else
120
- build_error_response(error)
121
- end
128
+ url = "#{Authy.api_uri}/#{eval_uri(uri, params)}"
129
+ params = clean_uri_params(uri_params, params)
130
+ http_client.post(url, :body => escape_query(params), header: header_)
131
+ else
132
+ build_error_response(error)
133
+ end
122
134
  Authy::Response.new(response)
123
135
  end
124
136
 
@@ -128,24 +140,24 @@ module Authy
128
140
  uri_params = keys_to_verify(uri, params)
129
141
  state, error = validate_for_url(uri_params, params)
130
142
  response = if state
131
- url = "#{Authy.api_uri}/#{eval_uri(uri, params)}"
132
- params = clean_uri_params(uri_params, params)
133
- http_client.get(url, params, header_)
134
- else
135
- build_error_response(error)
136
- end
143
+ url = "#{Authy.api_uri}/#{eval_uri(uri, params)}"
144
+ params = clean_uri_params(uri_params, params)
145
+ http_client.get(url, params, header_)
146
+ else
147
+ build_error_response(error)
148
+ end
137
149
  Authy::Response.new(response)
138
150
  end
139
151
 
140
152
  def self.build_error_response(error = "blank uri param found")
141
153
  OpenStruct.new({
142
- 'status' => 400,
143
- 'body' => {
144
- 'success' => false,
145
- 'message' => error,
146
- 'errors' => {
147
- 'message' => error
148
- }
154
+ "status" => 400,
155
+ "body" => {
156
+ "success" => false,
157
+ "message" => error,
158
+ "errors" => {
159
+ "message" => error,
160
+ },
149
161
  }.to_json
150
162
  })
151
163
  end
@@ -158,32 +170,26 @@ module Authy
158
170
  !!(/^\d+$/.match str.to_s)
159
171
  end
160
172
 
161
- def self.invalid_response(str="Invalid resonse")
173
+ def self.invalid_response(str = "Invalid resonse")
162
174
  response = build_error_response(str)
163
175
  return Authy::Response.new(response)
164
176
  end
165
177
 
166
178
  def self.verify_response(response)
167
- return response if response['token'] == 'is valid'
168
- response = build_error_response('Token is invalid')
179
+ return response if response["token"] == "is valid"
180
+ response = build_error_response("Token is invalid")
169
181
  return Authy::Response.new(response)
170
182
  end
171
183
 
172
- def self.default_header(api_key: nil, params: {})
184
+ def self.default_header(params: {})
185
+ api_key = params.delete(:api_key) || params.delete("api_key")
186
+
173
187
  header = {
174
188
  "X-Authy-API-Key" => api_key || Authy.api_key,
175
189
  "User-Agent" => Authy.user_agent
176
190
  }
177
191
 
178
- api_key_ = params.delete(:api_key) || params.delete("api_key")
179
-
180
- if api_key_ && api_key_.strip != ""
181
- AUTHY_LOGGER.warn("[DEPRECATED]: The Authy API key should not be sent as a parameter. Please send the HTTP header 'X-Authy-API-Key' instead.")
182
- header["X-Authy-API-Key"] = api_key_
183
- end
184
-
185
192
  return header
186
193
  end
187
-
188
194
  end
189
195
  end
@@ -23,7 +23,7 @@ module Authy
23
23
  begin
24
24
  self.clean_hash!(details)
25
25
  self.clean_hash!(hidden_details)
26
- self.clean_logos!(logos)
26
+ logos = self.clean_logos!(logos)
27
27
  rescue => e
28
28
  return invalid_response("Invalid parameters: #{e.message}")
29
29
  end
@@ -6,8 +6,11 @@ module Authy
6
6
  # :phone_number The persons phone number.
7
7
  # :custom_code Pass along any generated custom code.
8
8
  # :custom_message Custom Message.
9
+ # :code_length Length of code to be sent(4-10).
10
+ # :locale The language of the message received by user.
9
11
  def self.start(params)
10
- params[:via] = "sms" unless %w(sms, call).include?(params[:via])
12
+ warn "Authy Phone Verification has been superseded by the Twilio Verify API. Check https://twil.io/verify-start-ruby to see how to start a verification with the Twilio Verify API."
13
+ params[:via] = "sms" unless %w(sms call).include?(params[:via])
11
14
 
12
15
  post_request("protected/json/phones/verification/start", params)
13
16
  end
@@ -17,8 +20,8 @@ module Authy
17
20
  # :phone_number The persons phone number.
18
21
  # :verification_code The verification code entered by the user.
19
22
  def self.check(params)
23
+ warn "Authy Phone Verification has been superseded by the Twilio Verify API. Check https://twil.io/verify-check-ruby to see how to check a verification the Twilio Verify API."
20
24
  get_request("protected/json/phones/verification/check", params)
21
25
  end
22
-
23
26
  end
24
27
  end
@@ -30,10 +30,6 @@ module Authy
30
30
  [ true, ""]
31
31
  end
32
32
 
33
- def escape_for_url(field)
34
- URI.escape(field.to_s.strip, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
35
- end
36
-
37
33
  def to_param(left, right)
38
34
  HTTP::Message.escape(left) + '=' + HTTP::Message.escape(right.to_s)
39
35
  end
@@ -1,3 +1,3 @@
1
1
  module Authy
2
- VERSION = "2.7.5"
2
+ VERSION = "3.0.0"
3
3
  end
@@ -1,9 +1,17 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
+
3
+ class Utils
4
+ include Authy::URL
5
+ end
2
6
 
3
7
  describe "Authy::API" do
8
+ let(:headers) { { "X-Authy-API-Key" => Authy.api_key, "User-Agent" => "AuthyRuby/#{Authy::VERSION} (#{RUBY_PLATFORM}, Ruby #{RUBY_VERSION})" } }
9
+ let(:user_id) { 81547 }
10
+ let(:invalid_api_key) { "invalid_api_key" }
11
+
4
12
  describe "request headers" do
5
13
  it "contains api key and user agent in header" do
6
- expect_any_instance_of(HTTPClient).to receive(:request).twice.with(any_args, hash_including(header: { "X-Authy-API-Key" => Authy.api_key, "User-Agent" => "AuthyRuby/#{Authy::VERSION} (#{RUBY_PLATFORM}, Ruby #{RUBY_VERSION})" }) ) { double(ok?: true, body: "", status: 200) }
14
+ expect_any_instance_of(HTTPClient).to receive(:request).twice.with(any_args, hash_including(header: headers)) { double(ok?: true, body: "", status: 200) }
7
15
 
8
16
  url = "protected/json/foo/2"
9
17
  Authy::API.get_request(url, {})
@@ -12,50 +20,130 @@ describe "Authy::API" do
12
20
  end
13
21
 
14
22
  describe "Registering users" do
15
- it "should find or create a user" do
16
- user = Authy::API.register_user(
23
+ let(:register_user_url) { "#{Authy.api_uri}/protected/json/users/new" }
24
+
25
+ it "should register a user successfully" do
26
+ user_attributes = {
17
27
  email: generate_email,
18
28
  cellphone: generate_cellphone,
19
29
  country_code: 1
20
- )
30
+ }
31
+ response_json = {
32
+ "message" => "User created successfully.",
33
+ "user" => { "id" => user_id },
34
+ "success" => true
35
+ }.to_json
36
+ expect(Authy::API.http_client).to receive(:request)
37
+ .once
38
+ .with(:post, register_user_url, {
39
+ :body => Utils.escape_query(
40
+ :user => user_attributes,
41
+ :send_install_link_via_sms => true
42
+ ),
43
+ :header => headers
44
+ })
45
+ .and_return(double(:status => 200, :body => response_json))
46
+
47
+ user = Authy::API.register_user(user_attributes)
21
48
 
22
49
  expect(user).to be_kind_of(Authy::Response)
23
50
  expect(user).to be_kind_of(Authy::User)
24
51
  expect(user).to_not be_nil
25
52
  expect(user.id).to_not be_nil
26
- expect(user.id).to be_kind_of(Integer)
53
+ expect(user.id).to be(user_id)
27
54
  end
28
55
 
29
56
  it "should return the error messages as a hash" do
30
- user = Authy::API.register_user(
57
+ user_attributes = {
31
58
  email: generate_email,
32
59
  cellphone: "abc-1234",
33
60
  country_code: 1
34
- )
61
+ }
62
+ response_json = {
63
+ "cellphone" => "is invalid",
64
+ "message" => "User was not valid",
65
+ "success" => false,
66
+ "errors" => {
67
+ "cellphone" => "is invalid",
68
+ "message" => "User was not valid"
69
+ },
70
+ "error_code" => "60027"
71
+ }.to_json
72
+
73
+ expect(Authy::API.http_client).to receive(:request)
74
+ .once
75
+ .with(:post, register_user_url, {
76
+ :body => Utils.escape_query(
77
+ :user => user_attributes,
78
+ :send_install_link_via_sms => true
79
+ ),
80
+ :header => headers
81
+ })
82
+ .and_return(double(:status => 400, :body => response_json))
83
+
84
+ user = Authy::API.register_user(user_attributes)
35
85
 
36
86
  expect(user.errors).to be_kind_of(Hash)
37
- expect(user.errors['cellphone']).to include 'is invalid'
87
+ expect(user.errors["cellphone"]).to include "is invalid"
38
88
  end
39
89
 
40
90
  it "should allow to override the API key" do
41
- user = Authy::API.register_user(
91
+ response_json = {
92
+ "error_code" => "60001",
93
+ "message" => "Invalid API key",
94
+ "errors" => {"message" => "Invalid API key"},
95
+ "success" => false
96
+ }.to_json
97
+ user_attributes = {
42
98
  email: generate_email,
43
99
  cellphone: generate_cellphone,
44
100
  country_code: 1,
45
- api_key: "invalid_api_key"
46
- )
101
+ api_key: invalid_api_key
102
+ }
103
+
104
+ headers["X-Authy-API-Key"] = invalid_api_key
105
+
106
+ expect(Authy::API.http_client).to receive(:request)
107
+ .once
108
+ .with(:post, register_user_url, {
109
+ :body => Utils.escape_query(
110
+ :user => user_attributes.reject { |k,v| k === :api_key },
111
+ :send_install_link_via_sms => true
112
+ ),
113
+ :header => headers
114
+ })
115
+ .and_return(double(:status => 401, :body => response_json))
116
+
117
+ user = Authy::API.register_user(user_attributes)
47
118
 
48
119
  expect(user).to_not be_ok
49
- expect(user.errors['message']).to match(/invalid api key/i)
120
+ expect(user.errors["message"]).to match(/invalid api key/i)
50
121
  end
51
122
 
52
123
  it "should allow overriding send_install_link_via_sms default" do
53
- user = Authy::API.register_user(
124
+ response_json = {
125
+ "message" => "User created successfully.",
126
+ "user" => { "id" => user_id },
127
+ "success" => true
128
+ }.to_json
129
+ user_attributes = {
54
130
  email: generate_email,
55
131
  cellphone: generate_cellphone,
56
132
  country_code: 1,
57
- send_install_link_via_sms: false # Default is true. See http://docs.authy.com/totp.html#totp-api
58
- )
133
+ send_install_link_via_sms: false
134
+ }
135
+ expect(Authy::API.http_client).to receive(:request)
136
+ .once
137
+ .with(:post, register_user_url, {
138
+ :body => Utils.escape_query(
139
+ :user => user_attributes.reject { |k,v| k === :send_install_link_via_sms },
140
+ :send_install_link_via_sms => false
141
+ ),
142
+ :header => headers
143
+ })
144
+ .and_return(double(:status => 200, :body => response_json))
145
+
146
+ user = Authy::API.register_user(user_attributes)
59
147
 
60
148
  expect(user).to be_kind_of(Authy::Response)
61
149
  expect(user).to be_kind_of(Authy::User)
@@ -63,90 +151,98 @@ describe "Authy::API" do
63
151
  expect(user.id).to_not be_nil
64
152
  expect(user.id).to be_kind_of(Integer)
65
153
  end
66
-
67
154
  end
68
155
 
69
- describe "verificating tokens" do
70
- before do
71
- @email = generate_email
72
- @cellphone = generate_cellphone
73
- @user = Authy::API.register_user(
74
- email: @email,
75
- cellphone: @cellphone,
76
- country_code: 1
77
- )
78
- expect(@user).to be_ok
79
- end
156
+ describe "verifying tokens" do
157
+ let(:token) { "123456" }
158
+ let(:verify_url) { "#{Authy.api_uri}/protected/json/verify/#{token}/#{user_id}" }
80
159
 
81
- it "should fail to validate a given token if the user is not registered" do
82
- response = Authy::API.verify(token: 'invalid_token', id: @user.id)
160
+ it "should fail to validate a given token if the token is the wrong format" do
161
+ expect(Authy::API.http_client).to receive(:request).never
162
+ response = Authy::API.verify(token: "invalid_token", id: user_id)
83
163
 
84
164
  expect(response).to be_kind_of(Authy::Response)
85
165
  expect(response.ok?).to be_falsey
86
- expect(response.errors['message']).to include 'Token format is invalid'
166
+ expect(response.errors["message"]).to include "Token format is invalid"
87
167
  end
88
168
 
89
169
  it "should allow to override the API key" do
90
- response = Authy::API.verify(token: '123456', id: @user['id'], api_key: "invalid_api_key")
170
+ response_json = {
171
+ "error_code" => "60001",
172
+ "message" => "Invalid API key",
173
+ "errors" => {"message" => "Invalid API key"},
174
+ "success" => false
175
+ }.to_json
176
+ headers["X-Authy-API-Key"] = invalid_api_key
177
+ expect(Authy::API.http_client).to receive(:request)
178
+ .once
179
+ .with(:get, verify_url, {
180
+ :query => { :force => true },
181
+ :header => headers,
182
+ :follow_redirect => nil
183
+ })
184
+ .and_return(double(:status => 401, :body => response_json))
185
+
186
+ response = Authy::API.verify(token: "123456", id: user_id, api_key: invalid_api_key)
91
187
 
92
188
  expect(response).to_not be_ok
93
- expect(response.errors['message']).to match(/invalid api key/i)
189
+ expect(response.errors["message"]).to match(/invalid api key/i)
94
190
  end
95
191
 
96
192
  it "should escape the params" do
193
+ expect(Authy::API.http_client).to receive(:request).never
97
194
  expect do
98
- Authy::API.verify(token: '[=#%@$&#(!@);.,', id: @user['id'])
195
+ Authy::API.verify(token: "[=#%@$&#(!@);.,", id: user_id)
99
196
  end.to_not raise_error
100
197
  end
101
198
 
102
199
  it "should escape the params if have white spaces" do
200
+ expect(Authy::API.http_client).to receive(:request).never
103
201
  expect do
104
- Authy::API.verify(token: "token with space", id: @user['id'])
202
+ Authy::API.verify(token: "token with space", id: user_id)
105
203
  end.to_not raise_error
106
204
  end
107
205
 
108
206
  it "should fail if a param is missing" do
109
- response = Authy::API.verify(id: @user['id'])
207
+ expect(Authy::API.http_client).to receive(:request).never
208
+ response = Authy::API.verify(id: user_id)
110
209
  expect(response).to be_kind_of(Authy::Response)
111
210
  expect(response).to_not be_ok
112
- expect(response["message"]).to include('Token format is invalid')
211
+ expect(response["message"]).to include("Token format is invalid")
113
212
  end
114
213
 
115
- it 'fails when token format is invalid' do
116
- response = Authy::API.verify(token: '0000', id: @user.id)
214
+ it "fails when token format is invalid" do
215
+ expect(Authy::API.http_client).to receive(:request).never
216
+ response = Authy::API.verify(token: "0000", id: user_id)
117
217
 
118
218
  expect(response.ok?).to be_falsey
119
219
  expect(response).to be_kind_of(Authy::Response)
120
- expect(response.errors['message']).to eq 'Token format is invalid'
220
+ expect(response.errors["message"]).to eq "Token format is invalid"
121
221
  end
122
222
  end
123
223
 
124
224
  describe "requesting qr code for other authenticator apps" do
125
- before do
126
- @user = Authy::API.register_user(email: generate_email, cellphone: generate_cellphone, country_code: 1)
127
- expect(@user).to be_ok
128
- end
129
-
130
225
  it "should request qrcode" do
131
- url = "#{Authy.api_uri}/protected/json/users/#{Authy::API.escape_for_url(@user.id)}/secret"
132
- expect_any_instance_of(HTTPClient).to receive(:request).with(:post, url, body: "qr_size=300&label=example+app+name", header: {"X-Authy-API-Key" => Authy.api_key, "User-Agent" => "AuthyRuby/#{Authy::VERSION} (#{RUBY_PLATFORM}, Ruby #{RUBY_VERSION})"}) { double(ok?: true, body: "", status: 200) }
133
- response = Authy::API.send("request_qr_code", id: @user.id, qr_size: 300, qr_label: "example app name")
226
+ url = "#{Authy.api_uri}/protected/json/users/#{user_id}/secret"
227
+ expect_any_instance_of(HTTPClient).to receive(:request).with(:post, url, body: "qr_size=300&label=example+app+name", header: { "X-Authy-API-Key" => Authy.api_key, "User-Agent" => "AuthyRuby/#{Authy::VERSION} (#{RUBY_PLATFORM}, Ruby #{RUBY_VERSION})" }) { double(ok?: true, body: "", status: 200) }
228
+ response = Authy::API.send("request_qr_code", id: user_id, qr_size: 300, qr_label: "example app name")
134
229
  expect(response).to be_ok
135
230
  end
136
231
 
137
-
138
232
  context "user id is not a number" do
139
233
  it "should not be ok" do
234
+ expect(Authy::API.http_client).to receive(:request).never
140
235
  response = Authy::API.send("request_qr_code", id: "tony")
141
- expect(response.errors['message']).to eq "User id is invalid"
236
+ expect(response.errors["message"]).to eq "User id is invalid"
142
237
  expect(response).to_not be_ok
143
238
  end
144
239
  end
145
240
 
146
241
  context "qr size is not a number" do
147
242
  it "should return the right error" do
148
- response = Authy::API.send("request_qr_code", id: @user.id, qr_size: "notanumber")
149
- expect(response.errors['message']).to eq "Qr image size is invalid"
243
+ expect(Authy::API.http_client).to receive(:request).never
244
+ response = Authy::API.send("request_qr_code", id: user_id, qr_size: "notanumber")
245
+ expect(response.errors["message"]).to eq "Qr image size is invalid"
150
246
  expect(response).to_not be_ok
151
247
  end
152
248
  end
@@ -155,58 +251,212 @@ describe "Authy::API" do
155
251
  ["sms", "phone_call"].each do |kind|
156
252
  title = kind.upcase
157
253
  describe "Requesting #{title}" do
158
- before do
159
- @user = Authy::API.register_user(email: generate_email, cellphone: generate_cellphone, country_code: 1)
160
- expect(@user).to be_ok
161
- end
254
+ let(:uri_param) { kind == "phone_call" ? "call" : kind }
255
+ let(:url) { "#{Authy.api_uri}/protected/json/#{uri_param}/#{user_id}" }
162
256
 
163
257
  it "should request a #{title} token" do
164
- uri_param = kind == "phone_call" ? "call" : kind
165
- url = "#{Authy.api_uri}/protected/json/#{uri_param}/#{Authy::API.escape_for_url(@user.id)}"
166
- expect_any_instance_of(HTTPClient).to receive(:request).with(:get, url, {query:{}, header:{ "X-Authy-API-Key" => Authy.api_key, "User-Agent" => "AuthyRuby/#{Authy::VERSION} (#{RUBY_PLATFORM}, Ruby #{RUBY_VERSION})" }, follow_redirect:nil}) { double(ok?: true, body: "", status: 200) }
167
- response = Authy::API.send("request_#{kind}", id: @user.id)
258
+ expect_any_instance_of(HTTPClient).to receive(:request).with(:get, url, { query: {}, header: { "X-Authy-API-Key" => Authy.api_key, "User-Agent" => "AuthyRuby/#{Authy::VERSION} (#{RUBY_PLATFORM}, Ruby #{RUBY_VERSION})" }, follow_redirect: nil }) { double(ok?: true, body: "", status: 200) }
259
+ response = Authy::API.send("request_#{kind}", id: user_id)
168
260
  expect(response).to be_ok
169
261
  end
170
262
 
171
263
  it "should allow to override the API key" do
172
- response = Authy::API.send("request_#{kind}", id: @user.id, api_key: "invalid_api_key")
264
+ response_json = {
265
+ "error_code" => "60001",
266
+ "message" => "Invalid API key",
267
+ "errors" => {"message" => "Invalid API key"},
268
+ "success" => false
269
+ }.to_json
270
+ headers["X-Authy-API-Key"] = invalid_api_key
271
+ expect(Authy::API.http_client).to receive(:request)
272
+ .once
273
+ .with(:get, url, {
274
+ :header => headers,
275
+ :query => {},
276
+ :follow_redirect => nil
277
+ })
278
+ .and_return(double(:status => 401, :body => response_json))
279
+ response = Authy::API.send("request_#{kind}", id: user_id, api_key: invalid_api_key)
173
280
  expect(response).to_not be_ok
174
- expect(response.errors['message']).to match(/invalid api key/i)
281
+ expect(response.errors["message"]).to match(/invalid api key/i)
175
282
  end
176
283
 
177
284
  it "should request a #{title} token using custom actions" do
178
- response = Authy::API.send("request_#{kind}", id: @user.id, action: "custom action?", action_message: "Action message $%^?@#")
285
+ response_json = {
286
+ :success => true
287
+ }.to_json
288
+ expect(Authy::API.http_client).to receive(:request)
289
+ .once
290
+ .with(:get, url, {
291
+ :header => headers,
292
+ :query => {
293
+ :action => "custom action?",
294
+ :action_message => "Action message $%^?@#"
295
+ },
296
+ :follow_redirect => nil
297
+ })
298
+ .and_return(double(:status => 200, :body => response_json))
299
+ response = Authy::API.send("request_#{kind}", id: user_id, action: "custom action?", action_message: "Action message $%^?@#")
179
300
  expect(response).to be_ok
180
301
  end
181
302
 
182
303
  context "user doesn't exist" do
183
304
  it "should not be ok" do
305
+ url = "#{Authy.api_uri}/protected/json/#{uri_param}/tony"
306
+ response_json = {
307
+ "message" => "User not found.",
308
+ "success" => false,
309
+ "errors" => { "message" => "User not found." },
310
+ "error_code" => "60026"
311
+ }.to_json
312
+ expect(Authy::API.http_client).to receive(:request)
313
+ .once
314
+ .with(:get, url, {
315
+ :header => headers,
316
+ :query => { },
317
+ :follow_redirect => nil
318
+ })
319
+ .and_return(double(:status => 404, :body => response_json))
184
320
  response = Authy::API.send("request_#{kind}", id: "tony")
185
- expect(response.errors['message']).to eq "User not found."
321
+ expect(response.errors["message"]).to eq "User not found."
186
322
  expect(response).to_not be_ok
187
323
  end
188
324
  end
189
325
  end
190
326
  end
191
327
 
192
- describe "delete users" do
328
+ describe "Requesting email" do
329
+ it "should request an email token" do
330
+ response_json = {
331
+ "success" => true,
332
+ "message" => "Email token was sent",
333
+ "email" => "recipient@foo.com",
334
+ "email_id" => "EMa364aa751cc280d8c22772307e2c5760"
335
+ }.to_json
336
+ url = "#{Authy.api_uri}/protected/json/email/#{user_id}"
337
+
338
+ expect(Authy::API.http_client).to receive(:request)
339
+ .once
340
+ .with(:post, url, body: "", header: headers)
341
+ .and_return(double(ok?: true, body: response_json, status: 200))
342
+ response = Authy::API.request_email(id: user_id)
343
+ expect(response).to be_ok
344
+ end
345
+
193
346
  context "user doesn't exist" do
194
347
  it "should not be ok" do
195
- response = Authy::API.delete_user(id: "tony")
348
+ url = "#{Authy.api_uri}/protected/json/email/tony"
349
+ response_json = {
350
+ "message" => "User not found.",
351
+ "success" => false,
352
+ "errors" => {
353
+ "message" => "User not found."
354
+ },
355
+ "error_code" => "60026"
356
+ }.to_json
357
+ expect(Authy::API.http_client).to receive(:request)
358
+ .once
359
+ .with(:post, url, {
360
+ :header => headers,
361
+ :body => ""
362
+ })
363
+ .and_return(double(:status => 404, :body => response_json))
364
+ response = Authy::API.request_email(id: "tony")
365
+ expect(response.errors['message']).to eq "User not found."
366
+ expect(response).to_not be_ok
367
+ end
368
+ end
369
+ end
370
+
371
+ describe "update user email" do
372
+ context "user doesn't exist" do
373
+ it "should not be ok" do
374
+ url = "#{Authy.api_uri}/protected/json/users/tony/update"
375
+ response_json = {
376
+ "message" => "User not found.",
377
+ "success" => false,
378
+ "errors" => {
379
+ "message" => "User not found."
380
+ },
381
+ "error_code" => "60026"
382
+ }.to_json
383
+ new_email = generate_email
384
+ expect(Authy::API.http_client).to receive(:request)
385
+ .once
386
+ .with(:post, url, {
387
+ :header => headers,
388
+ :body => Utils.escape_query(:email => new_email)
389
+ })
390
+ .and_return(double(:status => 404, :body => response_json))
391
+
392
+ response = Authy::API.update_user(id: "tony", email: new_email)
196
393
  expect(response.errors['message']).to eq "User not found."
197
394
  expect(response).to_not be_ok
198
395
  end
199
396
  end
200
397
 
201
398
  context "user exists" do
202
- before do
203
- @user = Authy::API.register_user(email: generate_email, cellphone: generate_cellphone, country_code: 1)
204
- expect(@user).to be_ok
399
+ it "should be ok" do
400
+ response_json = {
401
+ "message" => "User was updated successfully",
402
+ "success" => true
403
+ }.to_json
404
+ url = "#{Authy.api_uri}/protected/json/users/#{user_id}/update"
405
+ new_email = generate_email
406
+ expect(Authy::API.http_client).to receive(:request)
407
+ .once
408
+ .with(:post, url, body: Utils.escape_query({
409
+ email: new_email
410
+ }), header: headers)
411
+ .and_return(double(ok?: true, body: response_json, status: 200))
412
+ response = Authy::API.update_user(id: user_id, email: new_email)
413
+ expect(response.message).to eq "User was updated successfully"
414
+ expect(response).to be_ok
205
415
  end
416
+ end
417
+ end
206
418
 
419
+ describe "delete users" do
420
+ context "user doesn't exist" do
421
+ it "should not be ok" do
422
+ url = "#{Authy.api_uri}/protected/json/users/delete/tony"
423
+ response_json = {
424
+ "message" => "User not found.",
425
+ "success" => false,
426
+ "errors" => {
427
+ "message" => "User not found."
428
+ },
429
+ "error_code" => "60026"
430
+ }.to_json
431
+ expect(Authy::API.http_client).to receive(:request)
432
+ .once
433
+ .with(:post, url, {
434
+ :header => headers,
435
+ :body => ""
436
+ })
437
+ .and_return(double(:status => 404, :body => response_json))
438
+ response = Authy::API.delete_user(id: "tony")
439
+ expect(response.errors["message"]).to eq "User not found."
440
+ expect(response).to_not be_ok
441
+ end
442
+ end
443
+
444
+ context "user exists" do
445
+ let(:url) { "#{Authy.api_uri}/protected/json/users/delete/31567" }
207
446
  it "should be ok" do
208
- response = Authy::API.delete_user(id: @user.id)
209
- expect(response.message).to eq "User was added to remove."
447
+ response_json = {
448
+ "message" => "User removed from application",
449
+ "success" => false
450
+ }.to_json
451
+ expect(Authy::API.http_client).to receive(:request)
452
+ .once
453
+ .with(:post, url, {
454
+ :header => headers,
455
+ :body => ""
456
+ })
457
+ .and_return(double(:status => 200, :body => response_json))
458
+ response = Authy::API.delete_user(id: 31567)
459
+ expect(response.message).to eq "User removed from application"
210
460
  expect(response).to be_ok
211
461
  end
212
462
  end
@@ -215,6 +465,23 @@ describe "Authy::API" do
215
465
  describe "user status" do
216
466
  context "user doesn't exist" do
217
467
  it "should not be ok" do
468
+ url = "#{Authy.api_uri}/protected/json/users/tony/status"
469
+ response_json = {
470
+ "message" => "User not found.",
471
+ "success" => false,
472
+ "errors" => {
473
+ "message" => "User not found."
474
+ },
475
+ "error_code" => "60026"
476
+ }.to_json
477
+ expect(Authy::API.http_client).to receive(:request)
478
+ .once
479
+ .with(:get, url, {
480
+ :header => headers,
481
+ :query => {},
482
+ :follow_redirect => nil
483
+ })
484
+ .and_return(double(:status => 404, :body => response_json))
218
485
  response = Authy::API.user_status(id: "tony")
219
486
  expect(response.errors["message"]).to eq "User not found."
220
487
  expect(response).to_not be_ok
@@ -222,13 +489,42 @@ describe "Authy::API" do
222
489
  end
223
490
 
224
491
  context "user exists" do
225
- before do
226
- @user = Authy::API.register_user(email: generate_email, cellphone: generate_cellphone, country_code: 1)
227
- expect(@user).to be_ok
228
- end
229
-
230
492
  it "should be ok" do
231
- response = Authy::API.user_status(id: @user.id)
493
+ url = "#{Authy.api_uri}/protected/json/users/290907/status"
494
+ response_json = {
495
+ "status" => {
496
+ "authy_id" => 290907,
497
+ "confirmed" => true,
498
+ "registered" => false,
499
+ "country_code" => 1,
500
+ "phone_number" => "XXX-XXX-1118",
501
+ "email" => "alfvawmu@authy.com",
502
+ "devices" => [],
503
+ "has_hard_token" => false,
504
+ "account_disabled" => false,
505
+ "detailed_devices" => [{
506
+ "device_type" => "authy",
507
+ "os_type" => "unknown",
508
+ "registration_device_id" => nil,
509
+ "registration_method" => nil,
510
+ "device_id" => 290908,
511
+ "last_sync_date" => 0,
512
+ "creation_date" => 1433868212
513
+ }],
514
+ "deleted_devices" => []
515
+ },
516
+ "message" => "User status.",
517
+ "success" => true
518
+ }.to_json
519
+ expect(Authy::API.http_client).to receive(:request)
520
+ .once
521
+ .with(:get, url, {
522
+ :header => headers,
523
+ :query => {},
524
+ :follow_redirect => nil
525
+ })
526
+ .and_return(double(:status => 200, :body => response_json))
527
+ response = Authy::API.user_status(id: 290907)
232
528
  expect(response.status).to be_kind_of(Hash)
233
529
  expect(response).to be_ok
234
530
  end
@@ -236,13 +532,9 @@ describe "Authy::API" do
236
532
  end
237
533
 
238
534
  describe "blank params" do
239
- before do
240
- @user = Authy::API.register_user(email: generate_email, cellphone: generate_cellphone, country_code: 1)
241
- expect(@user).to be_ok
242
- end
243
-
244
535
  [:request_sms, :request_phone_call, :delete_user].each do |method|
245
536
  it "should return a proper response with the errors for #{method}" do
537
+ expect(Authy::API.http_client).to receive(:request).never
246
538
  response = Authy::API.send(method, id: nil)
247
539
  expect(response).to_not be_ok
248
540
  expect(response.message).to eq "user_id is blank."
@@ -250,25 +542,26 @@ describe "Authy::API" do
250
542
  end
251
543
 
252
544
  it "should return a prope response with the errors for verify" do
545
+ expect(Authy::API.http_client).to receive(:request).never
253
546
  response = Authy::API.verify({})
254
547
  expect(response).to_not be_ok
255
548
  expect(response.message).to eq "Token format is invalid"
256
549
  end
257
550
  end
258
551
 
259
- describe '.token_is_safe?' do
260
- it 'checks minimum token size' do
261
- expect(Authy::API.send(:token_is_safe?, '1')).to be false
552
+ describe ".token_is_safe?" do
553
+ it "checks minimum token size" do
554
+ expect(Authy::API.send(:token_is_safe?, "1")).to be false
262
555
  end
263
556
 
264
- it 'checks valid characters' do
265
- expect(Authy::API.send(:token_is_safe?, '123456')).to be true
266
- expect(Authy::API.send(:token_is_safe?, '123456a')).to be false
557
+ it "checks valid characters" do
558
+ expect(Authy::API.send(:token_is_safe?, "123456")).to be true
559
+ expect(Authy::API.send(:token_is_safe?, "123456a")).to be false
267
560
  end
268
561
 
269
- it 'checks maximum token size' do
270
- expect(Authy::API.send(:token_is_safe?, '123456789098')).to be true
271
- expect(Authy::API.send(:token_is_safe?, '1234567890987')).to be false
562
+ it "checks maximum token size" do
563
+ expect(Authy::API.send(:token_is_safe?, "123456789098")).to be true
564
+ expect(Authy::API.send(:token_is_safe?, "1234567890987")).to be false
272
565
  end
273
566
  end
274
567
  end