forward 0.1.6 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/forward/api.rb +10 -7
- data/lib/forward/api/client_log.rb +1 -1
- data/lib/forward/api/resource.rb +14 -15
- data/lib/forward/api/tunnel.rb +27 -30
- data/lib/forward/api/tunnel_key.rb +3 -1
- data/lib/forward/api/user.rb +5 -4
- data/lib/forward/client.rb +22 -3
- data/lib/forward/tunnel.rb +9 -4
- data/lib/forward/version.rb +1 -1
- data/test/api/tunnel_key_test.rb +5 -5
- data/test/api/tunnel_test.rb +82 -44
- data/test/api/user_test.rb +19 -6
- data/test/tunnel_test.rb +22 -1
- metadata +2 -2
data/lib/forward/api.rb
CHANGED
@@ -9,12 +9,15 @@ module Forward
|
|
9
9
|
class BadResponse < StandardError; end
|
10
10
|
class ResourceNotFound < StandardError; end
|
11
11
|
class ResourceError < StandardError
|
12
|
-
attr_reader :action, :errors
|
12
|
+
attr_reader :code, :type, :action, :api_message, :errors
|
13
13
|
|
14
|
-
def initialize(action, json)
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@
|
14
|
+
def initialize(code, action, json = {})
|
15
|
+
@code = code
|
16
|
+
@action = action
|
17
|
+
@json = json
|
18
|
+
@type = json[:type]
|
19
|
+
@api_message = json[:message]
|
20
|
+
@errors = json[:errors] || {}
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
@@ -35,11 +38,11 @@ module Forward
|
|
35
38
|
end
|
36
39
|
|
37
40
|
def self.token=(token)
|
38
|
-
|
41
|
+
@api_token = token
|
39
42
|
end
|
40
43
|
|
41
44
|
def self.token
|
42
|
-
defined?(
|
45
|
+
defined?(@api_token) ? @api_token : nil
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
data/lib/forward/api/resource.rb
CHANGED
@@ -28,8 +28,6 @@ module Forward
|
|
28
28
|
response = @http.request(@request)
|
29
29
|
|
30
30
|
parse_response(response)
|
31
|
-
rescue ResourceError => e
|
32
|
-
self.class.dispatch_error(e)
|
33
31
|
end
|
34
32
|
|
35
33
|
def build_request(method, params = {})
|
@@ -77,10 +75,11 @@ module Forward
|
|
77
75
|
|
78
76
|
def parse_response(response)
|
79
77
|
log(:debug, "Response: [#{response.code}] `#{response.body}'")
|
78
|
+
code = response.code.to_i
|
80
79
|
|
81
|
-
if
|
80
|
+
if code == 404
|
82
81
|
raise ResourceNotFound
|
83
|
-
elsif
|
82
|
+
elsif ![ 200, 422, 401 ].include? code
|
84
83
|
raise BadResponse, "response code was: #{response.code}"
|
85
84
|
elsif response['content-type'] !~ /^application\/json/
|
86
85
|
raise BadResponse, "response was not JSON, unable to parse"
|
@@ -90,22 +89,22 @@ module Forward
|
|
90
89
|
|
91
90
|
if json.is_a? Hash
|
92
91
|
json.symbolize_keys!
|
93
|
-
raise ResourceError.new(@action, json) if
|
92
|
+
raise ResourceError.new(code, @action, json) if code != 200
|
94
93
|
end
|
95
94
|
|
96
95
|
json
|
97
96
|
end
|
98
97
|
|
99
|
-
def self.dispatch_error(error)
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
98
|
+
# def self.dispatch_error(error)
|
99
|
+
# Forward.log(:debug, "Dispatching ResourceError: action: #{error.action} errors: #{error.errors.inspect}")
|
100
|
+
# method = :"#{error.action}_error"
|
101
|
+
#
|
102
|
+
# if respond_to? method
|
103
|
+
# send(method, error.errors)
|
104
|
+
# else
|
105
|
+
# Forward::Client.cleanup_and_exit!('An error occured, please contact support@forwardhq.com')
|
106
|
+
# end
|
107
|
+
# end
|
109
108
|
|
110
109
|
private
|
111
110
|
|
data/lib/forward/api/tunnel.rb
CHANGED
@@ -4,7 +4,7 @@ module Forward
|
|
4
4
|
|
5
5
|
def self.create(options = {})
|
6
6
|
resource = Tunnel.new(:create)
|
7
|
-
resource.uri = '/api/tunnels'
|
7
|
+
resource.uri = '/api/v2/tunnels'
|
8
8
|
params = {
|
9
9
|
:hostport => options[:port],
|
10
10
|
:vhost => options[:host],
|
@@ -15,35 +15,39 @@ module Forward
|
|
15
15
|
params[param] = options[param] unless options[param].nil?
|
16
16
|
end
|
17
17
|
|
18
|
-
resource.post(params)
|
18
|
+
resource.post(params)[:tunnel].symbolize_keys
|
19
|
+
rescue ResourceError => e
|
20
|
+
error_on_create(e, options)
|
19
21
|
end
|
20
22
|
|
21
23
|
def self.index
|
22
24
|
resource = Tunnel.new(:index)
|
23
|
-
resource.uri = "/api/tunnels"
|
25
|
+
resource.uri = "/api/v2/tunnels"
|
24
26
|
|
25
|
-
resource.get
|
27
|
+
resource.get[:tunnels]
|
26
28
|
end
|
27
29
|
|
28
30
|
def self.destroy(id)
|
29
31
|
resource = Tunnel.new(:destroy)
|
30
|
-
resource.uri = "/api/tunnels/#{id}"
|
32
|
+
resource.uri = "/api/v2/tunnels/#{id}"
|
31
33
|
|
32
34
|
resource.delete
|
35
|
+
rescue ResourceError => e
|
36
|
+
nil
|
33
37
|
end
|
34
38
|
|
35
39
|
def self.show(id)
|
36
40
|
resource = Tunnel.new(:show)
|
37
|
-
resource.uri = "/api/tunnels/#{id}"
|
41
|
+
resource.uri = "/api/v2/tunnels/#{id}"
|
38
42
|
|
39
|
-
resource.get
|
43
|
+
resource.get[:tunnel].symbolize_keys
|
40
44
|
rescue Forward::Api::ResourceNotFound
|
41
45
|
nil
|
42
46
|
end
|
43
47
|
|
44
48
|
private
|
45
49
|
|
46
|
-
def self.ask_to_destroy(message)
|
50
|
+
def self.ask_to_destroy(message, options)
|
47
51
|
tunnels = index
|
48
52
|
|
49
53
|
puts message
|
@@ -51,49 +55,42 @@ module Forward
|
|
51
55
|
menu.prompt = "Choose a tunnel from the list to close or `q' to exit forward "
|
52
56
|
|
53
57
|
tunnels.each do |tunnel|
|
54
|
-
text = "
|
55
|
-
menu.choice(text) { destroy_and_create(tunnel['_id']) }
|
58
|
+
text = "Forwarding port #{tunnel['hostport']}"
|
59
|
+
menu.choice(text) { destroy_and_create(tunnel['_id'], options) }
|
56
60
|
end
|
57
61
|
menu.hidden('quit') { Forward::Client.cleanup_and_exit! }
|
58
62
|
menu.hidden('exit') { Forward::Client.cleanup_and_exit! }
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
62
|
-
def self.destroy_and_create(id)
|
66
|
+
def self.destroy_and_create(id, options)
|
63
67
|
Forward.log(:debug, "Destroying tunnel: #{id}")
|
64
68
|
destroy(id)
|
65
69
|
puts "tunnel removed, now we're creating a new one"
|
66
|
-
create(
|
70
|
+
create(options)
|
67
71
|
end
|
68
72
|
|
69
|
-
def self.
|
70
|
-
Forward.log(:debug, "An error occured creating tunnel:\n#{
|
71
|
-
base_errors = errors['base']
|
73
|
+
def self.error_on_create(error, options)
|
74
|
+
Forward.log(:debug, "An error occured creating tunnel:\n#{error.inspect}")
|
72
75
|
|
73
|
-
if
|
74
|
-
message = base_errors.select { |e| e.include? 'limit' }.first
|
76
|
+
if error.type == 'tunnel_limit_reached'
|
75
77
|
Forward.log(:debug, 'Tunnel limit reached')
|
76
|
-
ask_to_destroy(
|
78
|
+
ask_to_destroy(error.api_message, options)
|
79
|
+
elsif error.type =~ /(?:account_suspended|trial_expired)/i
|
80
|
+
Forward::Client.cleanup_and_exit!(error.api_message)
|
77
81
|
else
|
78
82
|
message = "We were unable to create your tunnel for the following reasons: \n"
|
79
|
-
errors.each do |key, value|
|
80
|
-
if key
|
81
|
-
message << " #{
|
82
|
-
|
83
|
-
|
84
|
-
message << " #{error}\n"
|
85
|
-
end
|
83
|
+
error.errors.each do |key, value|
|
84
|
+
if key == 'base'
|
85
|
+
message << " #{value.join(', ')}\n"
|
86
|
+
else
|
87
|
+
value.each { |m| message << " #{key} #{m}\n"}
|
86
88
|
end
|
87
89
|
end
|
88
90
|
Forward::Client.cleanup_and_exit!(message)
|
89
91
|
end
|
90
92
|
end
|
91
93
|
|
92
|
-
def self.destroy_error(errors)
|
93
|
-
# TODO: this is where we will tie into the logger
|
94
|
-
nil
|
95
|
-
end
|
96
|
-
|
97
94
|
end
|
98
95
|
end
|
99
96
|
end
|
@@ -4,11 +4,13 @@ module Forward
|
|
4
4
|
|
5
5
|
def self.create
|
6
6
|
resource = TunnelKey.new(:create)
|
7
|
-
resource.uri = '/api/tunnel_keys'
|
7
|
+
resource.uri = '/api/v2/tunnel_keys'
|
8
8
|
|
9
9
|
response = resource.post
|
10
10
|
|
11
11
|
response[:private_key]
|
12
|
+
rescue
|
13
|
+
Forward::Client.cleanup_and_exit!
|
12
14
|
end
|
13
15
|
|
14
16
|
end
|
data/lib/forward/api/user.rb
CHANGED
@@ -4,13 +4,14 @@ module Forward
|
|
4
4
|
|
5
5
|
def self.api_token(email, password)
|
6
6
|
resource = User.new(:api_token)
|
7
|
-
resource.uri = '/api/users/api_token'
|
7
|
+
resource.uri = '/api/v2/users/api_token'
|
8
8
|
params = { :email => email, :password => password }
|
9
9
|
|
10
|
-
resource.post(params)
|
11
|
-
|
10
|
+
user = resource.post(params)[:user].symbolize_keys
|
11
|
+
user[:id] = user.delete(:_id)
|
12
12
|
|
13
|
-
|
13
|
+
user
|
14
|
+
rescue ResourceError => e
|
14
15
|
Forward::Client.cleanup_and_exit!('Unable to authenticate with email and password')
|
15
16
|
end
|
16
17
|
|
data/lib/forward/client.rb
CHANGED
@@ -20,8 +20,9 @@ module Forward
|
|
20
20
|
if @tunnel.id
|
21
21
|
@tunnel.poll_status
|
22
22
|
else
|
23
|
-
cleanup_and_exit!('Unable to create a tunnel. If this continues contact support@forwardhq.com')
|
23
|
+
Forward::Client.cleanup_and_exit!('Unable to create a tunnel. If this continues contact support@forwardhq.com')
|
24
24
|
end
|
25
|
+
Forward.log(:debug, "Tunnel setup: #{@tunnel.inspect}")
|
25
26
|
|
26
27
|
@tunnel
|
27
28
|
end
|
@@ -48,6 +49,23 @@ module Forward
|
|
48
49
|
true
|
49
50
|
end
|
50
51
|
|
52
|
+
def self.forwarding_message(tunnel)
|
53
|
+
remote = "\033[04mhttps://#{@tunnel.subdomain}.fwd.wf\033[0m"
|
54
|
+
|
55
|
+
unless tunnel.cname.nil? || tunnel.cname.empty?
|
56
|
+
remote << " and \033[04mhttp://#{@tunnel.cname}\033[0m"
|
57
|
+
end
|
58
|
+
|
59
|
+
if !tunnel.vhost.nil? && tunnel.vhost !~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
|
60
|
+
local = tunnel.vhost
|
61
|
+
local << " port #{tunnel.hostport}" unless tunnel.hostport.to_i == 80
|
62
|
+
else
|
63
|
+
local = "port #{tunnel.hostport}"
|
64
|
+
end
|
65
|
+
|
66
|
+
"Forwarding #{local} to #{remote}\nCtrl-C to stop forwarding"
|
67
|
+
end
|
68
|
+
|
51
69
|
def self.start(options = {})
|
52
70
|
Forward.log(:debug, 'Starting client')
|
53
71
|
trap(:INT) { cleanup_and_exit!('closing tunnel and exiting...') }
|
@@ -56,8 +74,9 @@ module Forward
|
|
56
74
|
@tunnel = @client.setup_tunnel
|
57
75
|
@session = Net::SSH.start(@tunnel.tunneler, Forward.ssh_user, @client.ssh_options)
|
58
76
|
|
59
|
-
Forward.log(:debug, "Starting remote forward at #{@tunnel.subdomain}.fwd.wf
|
60
|
-
puts "Forwarding port #{@tunnel.hostport} at \033[04mhttps://#{@tunnel.subdomain}.fwd.wf\033[0m\nCtrl-C to stop forwarding"
|
77
|
+
Forward.log(:debug, "Starting remote forward at #{@tunnel.subdomain}.fwd.wf")
|
78
|
+
# puts "Forwarding port #{@tunnel.hostport} at \033[04mhttps://#{@tunnel.subdomain}.fwd.wf\033[0m\nCtrl-C to stop forwarding"
|
79
|
+
puts forwarding_message(@tunnel)
|
61
80
|
|
62
81
|
@session.forward.remote(@tunnel.hostport, @tunnel.host, @tunnel.port)
|
63
82
|
@session.loop { watch_session(@session) }
|
data/lib/forward/tunnel.rb
CHANGED
@@ -2,20 +2,24 @@ module Forward
|
|
2
2
|
class Tunnel
|
3
3
|
CHECK_INTERVAL = 7
|
4
4
|
|
5
|
-
# The Tunnel resource ID
|
5
|
+
# The Tunnel resource ID
|
6
6
|
attr_reader :id
|
7
|
-
# The domain for the Tunnel
|
7
|
+
# The domain for the Tunnel
|
8
8
|
attr_reader :subdomain
|
9
|
+
# The CNAME for the Tunnel
|
10
|
+
attr_reader :cname
|
9
11
|
# The host
|
10
12
|
attr_reader :host
|
11
13
|
# The vhost
|
12
14
|
attr_reader :vhost
|
13
15
|
# The hostport (local port)
|
14
16
|
attr_reader :hostport
|
15
|
-
# The remote port
|
17
|
+
# The remote port
|
16
18
|
attr_reader :port
|
17
|
-
# The tunneler host
|
19
|
+
# The tunneler host
|
18
20
|
attr_reader :tunneler
|
21
|
+
# The timeout
|
22
|
+
attr_reader :timeout
|
19
23
|
# The amount of time in seconds the Tunnel has be inactive for
|
20
24
|
attr_accessor :inactive_for
|
21
25
|
|
@@ -28,6 +32,7 @@ module Forward
|
|
28
32
|
@response = Forward::Api::Tunnel.create(options)
|
29
33
|
@id = @response[:_id]
|
30
34
|
@subdomain = @response[:subdomain]
|
35
|
+
@cname = @response[:cname]
|
31
36
|
@vhost = @response[:vhost]
|
32
37
|
@hostport = @response[:hostport]
|
33
38
|
@port = @response[:port]
|
data/lib/forward/version.rb
CHANGED
data/test/api/tunnel_key_test.rb
CHANGED
@@ -6,19 +6,19 @@ describe Forward::Api::TunnelKey do
|
|
6
6
|
FakeWeb.allow_net_connect = false
|
7
7
|
end
|
8
8
|
|
9
|
-
it
|
9
|
+
it "retrieves the public_key and returns it" do
|
10
10
|
fake_body = { :private_key => 'ssh-key 1234567890' }
|
11
11
|
|
12
|
-
stub_api_request(:post, '/api/tunnel_keys', :body => fake_body.to_json)
|
12
|
+
stub_api_request(:post, '/api/v2/tunnel_keys', :body => fake_body.to_json)
|
13
13
|
|
14
14
|
response = Api::TunnelKey.create
|
15
15
|
response.must_equal fake_body[:private_key]
|
16
16
|
end
|
17
17
|
|
18
|
-
it
|
19
|
-
fake_body = { :
|
18
|
+
it "exits with message if response has errors" do
|
19
|
+
fake_body = { :type => 'api_error' }
|
20
20
|
|
21
|
-
stub_api_request(:post, '/api/tunnel_keys', :body => fake_body.to_json)
|
21
|
+
stub_api_request(:post, '/api/v2/tunnel_keys', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
22
22
|
|
23
23
|
lambda {
|
24
24
|
dev_null { Api::TunnelKey.create }
|
data/test/api/tunnel_test.rb
CHANGED
@@ -7,66 +7,104 @@ describe Forward::Api::Tunnel do
|
|
7
7
|
Forward::Api.token = 'abc123'
|
8
8
|
end
|
9
9
|
|
10
|
-
it
|
11
|
-
|
12
|
-
fake_body = { :_id => '1', :subdomain => 'foo', :port => 56789 }
|
10
|
+
it "creates a tunnel and returns the attributes" do
|
11
|
+
fake_body = { :tunnel => { :_id => '1', :subdomain => 'foo', :port => 56789 }}
|
13
12
|
|
14
|
-
stub_api_request(:post, '/api/tunnels', :body => fake_body.to_json)
|
13
|
+
stub_api_request(:post, '/api/v2/tunnels', :body => fake_body.to_json)
|
15
14
|
|
16
15
|
response = Forward::Api::Tunnel.create(:port => 3000)
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
response[:_id].must_equal fake_body[:tunnel][:_id]
|
18
|
+
response[:subdomain].must_equal fake_body[:tunnel][:subdomain]
|
19
|
+
response[:port].must_equal fake_body[:tunnel][:port]
|
21
20
|
end
|
22
21
|
|
23
|
-
it
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
it "exits with message if create response is a resource_error" do
|
23
|
+
fake_body = {
|
24
|
+
:type => 'resource_error',
|
25
|
+
:errors => {
|
26
|
+
:base => [ 'did not work '],
|
27
|
+
:subdomain => [ 'is invalid', 'is too short' ]
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
stub_api_request(:post, '/api/v2/tunnels', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
32
|
+
|
33
|
+
out, err = capture_io do
|
34
|
+
begin
|
35
|
+
Forward::Api::Tunnel.create(:port => 3000)
|
36
|
+
rescue SystemExit; end
|
37
|
+
end
|
38
|
+
out.must_match /did not work/i
|
39
|
+
out.must_match /subdomain is invalid/i
|
40
|
+
out.must_match /subdomain is too short/i
|
32
41
|
end
|
33
42
|
|
34
|
-
it
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
43
|
+
it "exits with message if trial has expired" do
|
44
|
+
fake_body = {
|
45
|
+
:type => 'trial_expired',
|
46
|
+
:message => 'your trial has expired'
|
47
|
+
}
|
48
|
+
|
49
|
+
stub_api_request(:post, '/api/v2/tunnels', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
50
|
+
|
51
|
+
out, err = capture_io do
|
52
|
+
begin
|
53
|
+
Forward::Api::Tunnel.create(:port => 3000)
|
54
|
+
rescue SystemExit; end
|
55
|
+
end
|
56
|
+
out.must_match /trial has expired/i
|
57
|
+
end
|
58
|
+
|
59
|
+
it "exits with message if account has been suspended" do
|
60
|
+
fake_body = {
|
61
|
+
:type => 'account_suspended',
|
62
|
+
:message => 'your account has been suspended due for failed payment'
|
63
|
+
}
|
64
|
+
|
65
|
+
stub_api_request(:post, '/api/v2/tunnels', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
66
|
+
|
67
|
+
out, err = capture_io do
|
68
|
+
begin
|
69
|
+
Forward::Api::Tunnel.create(:port => 3000)
|
70
|
+
rescue SystemExit; end
|
71
|
+
end
|
72
|
+
out.must_match /account has been suspended/i
|
73
|
+
end
|
74
|
+
|
75
|
+
it "gives a choice and closes a tunnel if limit is reached" do
|
76
|
+
post_options = [
|
77
|
+
{ :body => { :type => 'tunnel_limit_reached', :message => 'you have reached your limit' }.to_json, :status => [ 422, 'Unprocessable Entity' ] },
|
78
|
+
{ :body => { :tunnel => { :_id => '1', :subdomain => 'foo', :port => 56789 } }.to_json }
|
79
|
+
]
|
80
|
+
index_body = { :tunnels => [ { :_id => 'abc123', :hostport => 1234 }, { :_id => 'def456', :hostport => 1235 } ] }
|
41
81
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
82
|
+
stub_api_request(:post, '/api/v2/tunnels', post_options)
|
83
|
+
stub_api_request(:get, '/api/v2/tunnels', :body => index_body.to_json)
|
84
|
+
STDIN.expects(:gets).returns('1')
|
85
|
+
Forward::Api::Tunnel.expects(:destroy).with(index_body[:tunnels].first[:_id])
|
46
86
|
|
47
|
-
|
48
|
-
|
87
|
+
dev_null { Forward::Api::Tunnel.create(:port => 3000) }
|
88
|
+
end
|
49
89
|
|
50
|
-
|
51
|
-
|
52
|
-
fake_body = { :_id => '1', :subdomain => 'foo', :port => 56789 }
|
90
|
+
it 'destroys a tunnel and returns the attributes' do
|
91
|
+
fake_body = { :_id => '1', :subdomain => 'foo', :port => 56789 }
|
53
92
|
|
54
|
-
|
93
|
+
stub_api_request(:delete, '/api/v2/tunnels/1', :body => fake_body.to_json)
|
55
94
|
|
56
|
-
|
95
|
+
response = Forward::Api::Tunnel.destroy(1)
|
57
96
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
97
|
+
fake_body.each do |key, value|
|
98
|
+
response[key].must_equal fake_body[key]
|
99
|
+
end
|
100
|
+
end
|
62
101
|
|
63
|
-
|
64
|
-
|
65
|
-
fake_body = { :errors => { :base => 'unable to create tunnel' } }
|
102
|
+
it 'gracefully handles the error if destroy has errors' do
|
103
|
+
fake_body = { :type => 'api_error' }
|
66
104
|
|
67
|
-
|
105
|
+
stub_api_request(:delete, '/api/v2/tunnels/1', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
68
106
|
|
69
|
-
|
70
|
-
|
107
|
+
Forward::Api::Tunnel.destroy(1).must_be_nil
|
108
|
+
end
|
71
109
|
|
72
110
|
end
|
data/test/api/user_test.rb
CHANGED
@@ -6,19 +6,32 @@ describe Forward::Api::User do
|
|
6
6
|
FakeWeb.allow_net_connect = false
|
7
7
|
end
|
8
8
|
|
9
|
-
it
|
10
|
-
fake_body
|
9
|
+
it "retrieves the users api token and returns it" do
|
10
|
+
fake_body = { :user => { :api_token => '123abc' } }
|
11
11
|
|
12
|
-
stub_api_request(:post, '/api/users/api_token', :body => fake_body.to_json)
|
12
|
+
stub_api_request(:post, '/api/v2/users/api_token', :body => fake_body.to_json)
|
13
13
|
|
14
14
|
response = Api::User.api_token('guy@example.com', 'secret')
|
15
15
|
response[:api_token].must_equal '123abc'
|
16
16
|
end
|
17
17
|
|
18
|
-
it
|
19
|
-
fake_body
|
18
|
+
it "exits with message if authentication fails" do
|
19
|
+
fake_body = { :type => 'api_error' }
|
20
20
|
|
21
|
-
stub_api_request(:post, '/api/users/api_token', :body => fake_body.to_json)
|
21
|
+
stub_api_request(:post, '/api/v2/users/api_token', :body => fake_body.to_json, :status => [ 401, 'Authentication Failed' ])
|
22
|
+
|
23
|
+
out, err = capture_io do
|
24
|
+
begin
|
25
|
+
Api::User.api_token('guy@example.com', 'secret')
|
26
|
+
rescue SystemExit; end
|
27
|
+
end
|
28
|
+
out.must_match /unable to authenticate/i
|
29
|
+
end
|
30
|
+
|
31
|
+
it "exits with message if response has errors" do
|
32
|
+
fake_body = { :type => 'api_error' }
|
33
|
+
|
34
|
+
stub_api_request(:post, '/api/v2/users/api_token', :body => fake_body.to_json, :status => [ 422, 'Unprocessable Entity' ])
|
22
35
|
|
23
36
|
lambda {
|
24
37
|
dev_null { Api::User.api_token('guy@example.com', 'secret') }
|
data/test/tunnel_test.rb
CHANGED
@@ -2,7 +2,28 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
describe Forward::Tunnel do
|
4
4
|
|
5
|
-
it
|
5
|
+
it "create a tunnel instance" do
|
6
|
+
tunnel_response = {
|
7
|
+
:_id => '1234',
|
8
|
+
:subdomain => 'foo',
|
9
|
+
:cname => 'foo.bar.com',
|
10
|
+
:vhost => '127.0.0.1',
|
11
|
+
:hostport => '3000',
|
12
|
+
:port => 20000,
|
13
|
+
:tunneler_public => 'test.forwardhq.com',
|
14
|
+
:timeout => 0
|
15
|
+
}
|
6
16
|
|
17
|
+
Forward::Api::Tunnel.expects(:create).returns(tunnel_response)
|
18
|
+
tunnel = Forward::Tunnel.new
|
19
|
+
|
20
|
+
tunnel.id.must_equal tunnel_response[:_id]
|
21
|
+
tunnel.subdomain.must_equal tunnel_response[:subdomain]
|
22
|
+
tunnel.cname.must_equal tunnel_response[:cname]
|
23
|
+
tunnel.vhost.must_equal tunnel_response[:vhost]
|
24
|
+
tunnel.hostport.must_equal tunnel_response[:hostport]
|
25
|
+
tunnel.port.must_equal tunnel_response[:port]
|
26
|
+
tunnel.tunneler.must_equal tunnel_response[:tunneler_public]
|
27
|
+
tunnel.timeout.must_equal tunnel_response[:timeout]
|
7
28
|
end
|
8
29
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forward
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|