vidibus-service 0.0.1

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.
@@ -0,0 +1,15 @@
1
+ module Vidibus # :nodoc
2
+ module Service # :nodoc
3
+ class Error < StandardError; end
4
+ end
5
+ end
6
+
7
+ require "service/client"
8
+ require "service/mongoid"
9
+ require "service/connector_app"
10
+ require "service/controller_validations"
11
+
12
+ # Shorthand for Service.discover
13
+ def Service(wanted, realm)
14
+ Service.discover(wanted, realm)
15
+ end
@@ -0,0 +1,14 @@
1
+ # require "rails"
2
+ require "vidibus-secure"
3
+ require "vidibus-validate_uri"
4
+ require "vidibus-uuid"
5
+ require "vidibus-core_extensions"
6
+
7
+ $:.unshift(File.join(File.dirname(__FILE__), "vidibus"))
8
+ require "service"
9
+
10
+ if defined?(Rails)
11
+ module Vidibus::Service
12
+ class Engine < ::Rails::Engine; end
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
+
4
+ require "rubygems"
5
+ require "active_support/core_ext"
6
+ require "rspec"
7
+ require "rr"
8
+ require "mongoid"
9
+ require "webmock/rspec"
10
+
11
+ require "vidibus-service"
12
+ require "app/models/service"
13
+
14
+ Mongoid.configure do |config|
15
+ name = "vidibus-service_test"
16
+ host = "localhost"
17
+ config.master = Mongo::Connection.new.db(name)
18
+ config.logger = nil
19
+ end
20
+
21
+ RSpec.configure do |config|
22
+ config.include WebMock
23
+ config.mock_with :rr
24
+ config.before(:each) do
25
+ Mongoid.master.collections.select {|c| c.name !~ /system/}.each(&:drop)
26
+ end
27
+ end
28
+
29
+ I18n.load_path += Dir[File.join('config', 'locales', '**', '*.{rb,yml}')]
30
+
31
+ #ENV["VIDIBUS_SECURE_KEY"] = "c4l60HC/lyerr2VEnrP7s2YAldyZGfIBePUzCl+tBsTs1EWJOc8dEJ7F2Vty7KPEeRuBWGxZHVAbku8pLo+UvXRpLcRiF7lxKiKl"
@@ -0,0 +1,73 @@
1
+ require "spec_helper"
2
+
3
+ describe Vidibus::Service::Client do
4
+ let(:this) {Service.create!(:function => "manager", :url => "http://manager.local", :uuid => "973a8710926e012d0a8c58b035f038ab", :secret => "EaDai5nz16DbQTWQuuFdd4WcAiZYRPDwZTn2IQeXbPE4yBg3rr", :this => true, :realm_uuid => nil)}
5
+ let(:uploader) {Service.create!(:function => "uploader", :url => "http://uploader.local", :uuid => "ddeb4500668e012d47bb58b035f038ab", :secret => "XaDai5nz1sDbQTWQuuFdd4WcAiZYRPDwZTn2IQeXbPE4yBg3rr", :realm_uuid => "e33f0d9093f9012d0dbc58b035f038ab")}
6
+ let(:client) { this; Vidibus::Service::Client.new(uploader) }
7
+
8
+ describe "#initialize" do
9
+ it "should require a service object" do
10
+ expect { Vidibus::Service::Client.new(:uploader) }.should raise_error(Vidibus::Service::Client::ServiceError)
11
+ end
12
+
13
+ it "should require this" do
14
+ expect { Vidibus::Service::Client.new(uploader) }.should raise_error(Service::ConfigurationError)
15
+ end
16
+
17
+ it "should set URL of given service as base_uri" do
18
+ this
19
+ client = Vidibus::Service::Client.new(uploader)
20
+ client.base_uri.should eql(uploader.url)
21
+ end
22
+ end
23
+
24
+ describe "#get" do
25
+ it "should load data via GET" do
26
+ stub_http_request(:get, "http://uploader.local/success").
27
+ with(:query => {:realm => uploader.realm_uuid, :service => this.uuid, :sign => "43a4d004c55113131f198c9772760467727b5564de74aacfcf4686751e3d388a"}).
28
+ to_return(:status => 200, :body => %({"hot":"stuff"}))
29
+ response = client.get("/success")
30
+ response.code.should eql(200)
31
+ response.should eql({"hot" => "stuff"})
32
+ end
33
+
34
+ it "should handle non-JSON responses" do
35
+ stub_http_request(:get, "http://uploader.local/success").
36
+ with(:query => {:realm => uploader.realm_uuid, :service => this.uuid, :sign => "43a4d004c55113131f198c9772760467727b5564de74aacfcf4686751e3d388a"}).
37
+ to_return(:status => 200, :body => "something")
38
+ response = client.get("/success")
39
+ response.code.should eql(200)
40
+ response.should eql("something")
41
+ end
42
+ end
43
+
44
+ describe "#post" do
45
+ it "should send data via POST" do
46
+ stub_http_request(:post, "http://uploader.local/create").
47
+ with(:body => {:some => "thing", :realm => uploader.realm_uuid, :service => this.uuid, :sign => "9c16bc080f106c73f28813f02899be97301b1b627d25a65d52f68a3c9732559d"}).
48
+ to_return(:status => 200)
49
+ response = client.post("/create", :body => {:some => "thing"})
50
+ response.code.should eql(200)
51
+ end
52
+ end
53
+
54
+ describe "#put" do
55
+ it "should send data via PUT" do
56
+ stub_http_request(:put, "http://uploader.local/update").
57
+ with(:body => {:some => "thing", :realm => uploader.realm_uuid, :service => this.uuid, :sign => "57e75433e49d9ef160b03b9e6a7d91fbd6523471eb8e7e36bb861066101f0903"}).
58
+ to_return(:status => 200)
59
+ response = client.put("/update", :body => {:some => "thing"})
60
+ response.code.should eql(200)
61
+ end
62
+ end
63
+
64
+ describe "#delete" do
65
+ it "should send a DELETE request" do
66
+ stub_http_request(:delete, "http://uploader.local/record/123").
67
+ with(:query => {:realm => uploader.realm_uuid, :service => this.uuid, :sign => "b9c026563d950a719e168c6f072f75c13f4843b82274f57f6e5a9a4cd8e0cc64"}).
68
+ to_return(:status => 200)
69
+ response = client.delete("/record/123")
70
+ response.code.should eql(200)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,246 @@
1
+ require "spec_helper.rb"
2
+
3
+ describe "Vidibus::Service::ConnectorApp" do
4
+ include Rack::Test::Methods
5
+
6
+ let(:this_params) { {"uuid" => "344b4b8088fb012dd3e558b035f038ab", "url" => "http://manager.local", "function" => "manager"} }
7
+ let(:connector_params) { {"uuid" => "60dfef509a8e012d599558b035f038ab", "url" => "https://connector.local"} }
8
+ let(:this) { Service.create!(this_params.merge(:secret => "EaDai5nz16DbQTWQuuFdd4WcAiZYRPDwZTn2IQeXbPE4yBg3rr", :realm_uuid => nil, :this => true)) }
9
+ let(:connector) { Service.create!(connector_params.merge(:function => "connector", :secret => nil, :realm_uuid => nil)) }
10
+
11
+ def app
12
+ @app ||= Vidibus::Service::ConnectorApp
13
+ end
14
+
15
+ # Sends a signed request.
16
+ def signed_request(method, url, params = nil)
17
+ self.send(method, *Vidibus::Secure.sign_request(method, url, params, this.secret))
18
+ end
19
+
20
+ it "should fail for request methods other than GET, POST, PUT, and DELETE" do
21
+ head "http://manager.local/connector"
22
+ last_response.status.should eql(400)
23
+ end
24
+
25
+ it "should fail for paths other than /connector" do
26
+ get "http://manager.local/something"
27
+ last_response.status.should eql(400)
28
+ last_response.body.should eql(%({"error":"This app must be configured to respond to /connector path."}))
29
+ end
30
+
31
+ describe "GET requests" do
32
+ it "should fail without signature" do
33
+ this and connector
34
+ get "http://manager.local/connector"
35
+ last_response.status.should eql(400)
36
+ last_response.body.should eql(%({"error":"Invalid signature."}))
37
+ end
38
+
39
+ it "should fail without valid signature" do
40
+ this and connector
41
+ get "http://manager.local/connector?sign=xxx"
42
+ last_response.status.should eql(400)
43
+ last_response.body.should eql(%({"error":"Invalid signature."}))
44
+ end
45
+
46
+ it "should fail without this service" do
47
+ connector
48
+ get "http://manager.local/connector"
49
+ last_response.status.should eql(400)
50
+ end
51
+
52
+ it "should return public data of this service as JSON" do
53
+ this
54
+ signed_request(:get, "http://manager.local/connector")
55
+ last_response.body.should eql({:this => this.public_data}.to_json)
56
+ last_response.status.should eql(200)
57
+ last_response.content_type.should eql("text/javascript; charset=utf-8")
58
+ end
59
+
60
+ it "should also return public data of connector as JSON, if a connector is given" do
61
+ this and connector
62
+ signed_request(:get, "http://manager.local/connector")
63
+ last_response.body.should eql({:this => this.public_data, :connector => connector.public_data}.to_json)
64
+ last_response.content_type.should eql("text/javascript; charset=utf-8")
65
+ end
66
+ end
67
+
68
+ describe "POST requests" do
69
+ it "should fail if this service has already been set up" do
70
+ this
71
+ post "http://manager/connector", {}
72
+ last_response.status.should eql(400)
73
+ last_response.body.should eql(%({"error":"Service has already been set up."}))
74
+ end
75
+
76
+ it "should require Connector params" do
77
+ post "http://manager.local/connector"
78
+ last_response.status.should eql(400)
79
+ last_response.body.should eql(%({"error":"No Connector data given."}))
80
+ end
81
+
82
+ it "should fail if Connector data is invalid" do
83
+ post "http://manager.local/connector", {:connector => {:some => "thing"}}
84
+ last_response.status.should eql(400)
85
+ last_response.body.should match("Setting up the Connector failed:")
86
+ end
87
+
88
+ it "should set up a Connector" do
89
+ mock(::Service).new(connector_params.merge(:function => "connector"))
90
+ expect {
91
+ post "http://manager.local/connector", {:connector => connector_params}
92
+ }.to raise_error(NoMethodError, "undefined method `save' for nil:NilClass")
93
+ end
94
+
95
+ context "with Connector or Connector params" do
96
+ before { connector }
97
+
98
+ it "should not require Connector params if a Connector is present" do
99
+ post "http://manager.local/connector"
100
+ last_response.body.should_not eql(%({"error":"No Connector data given."}))
101
+ end
102
+
103
+ it "should require params for this service" do
104
+ post "http://manager.local/connector"
105
+ last_response.status.should eql(400)
106
+ last_response.body.should eql(%({"error":"No data for this service given."}))
107
+ end
108
+
109
+ it "should fail if params for this service are invalid" do
110
+ post "http://manager.local/connector", {:this => {:some => "thing"}}
111
+ last_response.status.should eql(400)
112
+ last_response.body.should match("Setting up this service failed:")
113
+ end
114
+
115
+ it "should set up this Service" do
116
+ mock(::Service).new(this_params.merge(:this => true))
117
+ expect {
118
+ post "http://manager.local/connector", {:this => this_params}
119
+ }.to raise_error(NoMethodError, "undefined method `secret=' for nil:NilClass")
120
+ end
121
+
122
+ it "should request a secret for this Service" do
123
+ uri = "https://connector.local/services/#{this_params["uuid"]}/secret"
124
+ stub_http_request(:get, uri).to_return(:status => 200)
125
+ post "http://manager.local/connector", {:this => this_params}
126
+ end
127
+
128
+ it "should require a valid nonce to decrypt requested secret" do
129
+ uri = "https://connector.local/services/#{this_params["uuid"]}/secret"
130
+ params = {}
131
+ stub_http_request(:get, uri).to_return(:status => 200, :body => %({"secret":"something","sign":"else"}))
132
+ post "http://manager.local/connector", {:this => this_params.merge("nonce" => "invalid")}
133
+ last_response.status.should eql(400)
134
+ last_response.body.should match("Nonce is invalid.")
135
+ end
136
+
137
+ it "should decrypt requested secret and store it on the service object" do
138
+ nonce = "hkO2ssb28Gks19s9h2hdhbBs83hdis"
139
+ secret = "EaDai5nz16DbQTWQuuFdd4WcAiZYRPDwZTn2IQeXbPE4yBg3rr"
140
+ encrypted_secret = Vidibus::Secure.encrypt(secret, nonce)
141
+ signature = Vidibus::Secure.sign(encrypted_secret, nonce)
142
+ uri = "https://connector.local/services/#{this_params["uuid"]}/secret"
143
+ params = {:secret => encrypted_secret, :sign => signature}
144
+ stub_http_request(:get, uri).to_return(:status => 200, :body => params.to_json)
145
+ post "http://manager.local/connector", {:this => this_params.merge("nonce" => nonce)}
146
+ last_response.status.should eql(201)
147
+ this = ::Service.where(:this => true).first
148
+ this.should be_a(::Service)
149
+ this.secret.should eql(secret)
150
+ end
151
+ end
152
+ end
153
+
154
+ describe "PUT requests" do
155
+ it "should fail without signature" do
156
+ this and connector
157
+ put "http://manager.local/connector"
158
+ last_response.status.should eql(400)
159
+ last_response.body.should eql(%({"error":"Invalid signature."}))
160
+ end
161
+
162
+ it "should fail without valid signature" do
163
+ this and connector
164
+ put "http://manager.local/connector?sign=xxx"
165
+ last_response.status.should eql(400)
166
+ last_response.body.should eql(%({"error":"Invalid signature."}))
167
+ end
168
+
169
+ it "should succeed with valid signature" do
170
+ this and connector
171
+ signed_request(:put, "http://manager.local/connector")
172
+ last_response.status.should eql(200)
173
+ end
174
+
175
+ it "should fail if this service is unconfigured" do
176
+ get "http://manager.local/connector?sign=jkasdnkajdb"
177
+ last_response.status.should eql(400)
178
+ end
179
+
180
+ it "should update existing services" do
181
+ this and connector
182
+ url = "http://newconnector.local"
183
+ signed_request(:put, "http://manager.local/connector", {:connector => {:url => url}})
184
+ last_response.status.should eql(200)
185
+ Service.local(:connector).url.should eql(url)
186
+ end
187
+
188
+ it "should fail if invalid data are given" do
189
+ this and connector
190
+ url = "http://newconnector.local"
191
+ signed_request(:put, "http://manager.local/connector", {:connector => {:secret => "not allowed"}})
192
+ last_response.status.should eql(400)
193
+ last_response.body.should match("Updating connector failed:")
194
+ end
195
+
196
+ it "should create new services" do
197
+ this and connector
198
+ url = "http://newconnector.local"
199
+ signed_request(:put, "http://manager.local/connector",
200
+ {:uploader => {:url => "http://uploader.local", :uuid => "c0861d609247012d0a8b58b035f038ab", :secret => "A7q8Vzxgrk9xrw2FCnvV4bv01UP/LBUUM0lIGDmMcB2GsBTIqx", :realm_uuid => "12ab69f099a4012d4df558b035f038ab"}})
201
+ last_response.status.should eql(200)
202
+ Service.local(:uploader, "12ab69f099a4012d4df558b035f038ab").url.should eql("http://uploader.local")
203
+ end
204
+ end
205
+
206
+ describe "DELETE requests" do
207
+ it "should fail without signature" do
208
+ this and connector
209
+ delete "http://manager.local/connector"
210
+ last_response.status.should eql(400)
211
+ last_response.body.should eql(%({"error":"Invalid signature."}))
212
+ end
213
+
214
+ it "should fail without valid signature" do
215
+ this and connector
216
+ delete "http://manager.local/connector?sign=xxx"
217
+ last_response.status.should eql(400)
218
+ last_response.body.should eql(%({"error":"Invalid signature."}))
219
+ end
220
+
221
+ it "should fail if this service is unconfigured" do
222
+ delete "http://manager.local/connector?sign=jkasdnkajdb"
223
+ last_response.status.should eql(400)
224
+ end
225
+
226
+ it "should fail if list of UUIDs is not given" do
227
+ this and connector
228
+ signed_request(:delete, "http://manager.local/connector", {})
229
+ last_response.status.should eql(400)
230
+ last_response.body.should eql(%({"error":"Provide list of :uuids"}))
231
+ end
232
+
233
+ it "should delete services given by UUID" do
234
+ this and connector
235
+ signed_request(:delete, "http://manager.local/connector", {:uuids =>["60dfef509a8e012d599558b035f038ab"]})
236
+ last_response.status.should eql(200)
237
+ Service.local(:connector).should be_nil
238
+ end
239
+
240
+ it "should not care if any given UUID is invalid" do
241
+ this and connector
242
+ signed_request(:delete, "http://manager.local/connector", {:uuids =>["invalid", "60dfef509a8e012d599558b035f038ab"]})
243
+ last_response.status.should eql(200)
244
+ end
245
+ end
246
+ end
@@ -0,0 +1,5 @@
1
+ require "spec_helper"
2
+
3
+ describe "Vidibus::Service::ControllerValidations" do
4
+ it "should be spec'd"
5
+ end
@@ -0,0 +1,226 @@
1
+ require "spec_helper"
2
+
3
+ describe "Vidibus::Service::Mongoid" do
4
+ let(:realm) { "12ab69f099a4012d4df558b035f038ab" }
5
+ let(:this) { Service.create!(:function => "manager", :url => "http://manager.local", :uuid => "344b4b8088fb012dd3e558b035f038ab", :secret => "EaDai5nz16DbQTWQuuFdd4WcAiZYRPDwZTn2IQeXbPE4yBg3rr", :realm_uuid => nil, :this => true) }
6
+ let(:connector) { Service.create!(:function => "connector", :url => "http://connector.local", :uuid => "60dfef509a8e012d599558b035f038ab", :secret => nil, :realm_uuid => nil) }
7
+ let(:uploader) { Service.create!(:function => "uploader", :url => "http://uploader.local", :uuid => "c0861d609247012d0a8b58b035f038ab", :secret => "A7q8Vzxgrk9xrw2FCnvV4bv01UP/LBUUM0lIGDmMcB2GsBTIqx", :realm_uuid => realm) }
8
+ let(:client_mock) { this; mock.any_instance_of(Vidibus::Service::Client) }
9
+
10
+ describe "validation" do
11
+ it "should pass with valid attributes" do
12
+ this.should be_valid
13
+ end
14
+
15
+ it "should fail without a valid URL" do
16
+ this.url = "something"
17
+ this.should be_invalid
18
+ end
19
+
20
+ it "should fail without a function" do
21
+ this.function = ""
22
+ this.should be_invalid
23
+ this.errors[:function].should have(1).error
24
+ end
25
+
26
+ it "should pass with arbitrary functions" do
27
+ this.function = :something
28
+ this.should be_valid
29
+ end
30
+
31
+ it "should fail if a secret is given for Connector" do
32
+ connector.secret = "something"
33
+ connector.should be_invalid
34
+ connector.errors[:secret].should have(1).error
35
+ connector.errors[:secret].first.should eql("is not allowed for a Connector")
36
+ end
37
+
38
+ it "should pass with empty secret for Connector" do
39
+ connector.secret = nil
40
+ connector.should be_valid
41
+ end
42
+
43
+ it "should fail without a secret for services except Connector" do
44
+ uploader.secret = nil
45
+ uploader.should be_invalid
46
+ uploader.errors[:secret].should have(1).error
47
+ end
48
+
49
+ it "should fail without a realm_uuid for services except Connector and this" do
50
+ uploader.realm_uuid = nil
51
+ uploader.should be_invalid
52
+ uploader.errors[:realm_uuid].should have(1).error
53
+ end
54
+
55
+ it "should pass with empty realm_uuid for Connector" do
56
+ connector.realm_uuid = nil
57
+ connector.should be_valid
58
+ end
59
+
60
+ it "should pass if realm_uuid is given for Connector" do
61
+ connector.realm_uuid = realm
62
+ connector.should be_valid
63
+ end
64
+
65
+ it "should pass if a realm_uuid is given for this" do
66
+ this.realm_uuid = realm
67
+ this.should be_valid
68
+ end
69
+
70
+ it "should fail for duplicate UUIDs within same realm" do
71
+ duplicate_service = Service.new(:uuid => uploader.uuid, :realm_uuid => realm)
72
+ duplicate_service.should be_invalid
73
+ duplicate_service.errors[:uuid].should have(1).error
74
+ end
75
+ end
76
+
77
+ describe "#url" do
78
+ it "should be set without trailing slash" do
79
+ this.url = "http://manager.local/"
80
+ this.url.should eql("http://manager.local")
81
+ end
82
+
83
+ it "should be stored without trailing slash" do
84
+ this.update_attributes(:url => "http://manager.local/")
85
+ this.reload.url.should eql("http://manager.local")
86
+ end
87
+ end
88
+
89
+ describe "#domain" do
90
+ it "should return the url without protocol" do
91
+ this.domain.should eql(this.url.gsub(/https?:\/\//, ""))
92
+ end
93
+ end
94
+
95
+ describe "#connector?" do
96
+ it "should return true if service is a Connector" do
97
+ connector.connector?.should be_true
98
+ end
99
+
100
+ it "should return false if service is not a Connector" do
101
+ uploader.connector?.should be_false
102
+ end
103
+ end
104
+
105
+ describe "#get" do
106
+ it "should trigger a GET request" do
107
+ client_mock.get("/something", :query => { :gotta => "give" })
108
+ uploader.get("/something", :query => { :gotta => "give" })
109
+ end
110
+ end
111
+
112
+ describe "#post" do
113
+ it "should trigger a POST request" do
114
+ client_mock.post("/something", :query => { :do => "it" })
115
+ uploader.post("/something", :query => { :do => "it" })
116
+ end
117
+ end
118
+
119
+ describe "#put" do
120
+ it "should trigger a PUT request" do
121
+ client_mock.put("/something", :query => { :new => "stuff" })
122
+ uploader.put("/something", :query => { :new => "stuff" })
123
+ end
124
+ end
125
+
126
+ describe "#delete" do
127
+ it "should trigger a DELETE request" do
128
+ client_mock.delete("/something/else", {})
129
+ uploader.delete("/something/else")
130
+ end
131
+ end
132
+
133
+ describe ".this" do
134
+ it "should return this service" do
135
+ this
136
+ Service.this.should eql(this)
137
+ end
138
+
139
+ it "should raise an error if this service has not been configured yet" do
140
+ expect {Service.this}.to raise_error(Service::ConfigurationError)
141
+ end
142
+ end
143
+
144
+ describe ".connector" do
145
+ it "should return the Connector" do
146
+ connector
147
+ Service.connector.should eql(connector)
148
+ end
149
+
150
+ it "should raise an error if the Connector has not been configured yet" do
151
+ expect {Service.connector}.to raise_error(Service::ConfigurationError)
152
+ end
153
+ end
154
+
155
+ describe ".local" do
156
+ before {uploader}
157
+
158
+ it "should return a service matching given function without a realm" do
159
+ connector
160
+ Service.local(:connector).should eql(connector)
161
+ end
162
+
163
+ it "should return a service matching given function and realm" do
164
+ Service.local(:uploader, realm).should eql(uploader)
165
+ end
166
+
167
+ it "should return no service if it does not match given realm" do
168
+ Service.local(:uploader).should be_nil
169
+ end
170
+
171
+ it "should return no service if it does not match given function" do
172
+ Service.local(:connector, realm).should be_nil
173
+ end
174
+
175
+ it "should return a service matching given UUID and realm" do
176
+ Service.local(uploader.uuid, realm).should eql(uploader)
177
+ end
178
+
179
+ it "should return no service if it does not match given function" do
180
+ Service.local("123", realm).should be_nil
181
+ end
182
+ end
183
+
184
+ describe ".discover" do
185
+ it "should first try to find a local service" do
186
+ uploader
187
+ mock(Service).local(:uploader, realm) {uploader}
188
+ dont_allow(Service).remote(:uploader, realm)
189
+ Service.discover(:uploader, realm).should eql(uploader)
190
+ end
191
+
192
+ it "if no local service can be found a remote one should be fetched" do
193
+ mock(Service).local(:uploader, realm) {nil}
194
+ mock(Service).remote(:uploader, realm) {uploader}
195
+ Service.discover(:uploader, realm).should eql(uploader)
196
+ end
197
+ end
198
+
199
+ describe ".remote" do
200
+ it "should require a realm" do
201
+ expect {Service.remote(:uploader, nil)}.to raise_error(ArgumentError)
202
+ end
203
+
204
+ it "should fetch service data from Connector and create a local service object" do
205
+ connector and this
206
+ stub_http_request(:get, "http://connector.local/services/uploader").
207
+ with(:query => {:realm => "12ab69f099a4012d4df558b035f038ab", :service => "344b4b8088fb012dd3e558b035f038ab", :sign => "d27be37e9440765d38789f9000a5b3a86c741b3954c88f7b1769e4067ac9fbd0"}).
208
+ to_return(:status => 200, :body => %({"uuid":"c0861d609247012d0a8b58b035f038ab", "url":"http://uploader.local", "function":"uploader", "secret":"kjO8AjgX68Yp7OQ1XF8dTfPBE5GCuCnd/OPko+A9yCaw8qnj9xoyMGZEXQpf\niVBOUcux1qlW8hfT6UPKGoVfYA==\n"}))
209
+ Service.remote(:uploader, realm)
210
+
211
+ uploader = Service.local(:uploader, realm)
212
+ uploader.uuid.should eql("c0861d609247012d0a8b58b035f038ab")
213
+ uploader.function.should eql("uploader")
214
+ uploader.url.should eql("http://uploader.local")
215
+ uploader.secret.should eql(Vidibus::Secure.decrypt("kjO8AjgX68Yp7OQ1XF8dTfPBE5GCuCnd/OPko+A9yCaw8qnj9xoyMGZEXQpf\niVBOUcux1qlW8hfT6UPKGoVfYA==\n", this.secret))
216
+ end
217
+
218
+ it "should raise an error requested service has already been stored" do
219
+ connector and this and uploader
220
+ stub_http_request(:get, "http://connector.local/services/uploader").
221
+ with(:query => {:realm => "e75234809111012d05ac58b035f038ab", :service => "973a8710926e012d0a8c58b035f038ab", :sign => "a93d3a1a0124e969f97d68feab37638ec8737b1d8ddc582cd204fbb228ad7e2b"}).
222
+ to_return(:status => 200, :body => %({"uuid":"c0861d609247012d0a8b58b035f038ab", "url":"http://uploader.local", "function":"uploader", "secret":"kjO8AjgX68Yp7OQ1XF8dTfPBE5GCuCnd/OPko+A9yCaw8qnj9xoyMGZEXQpf\niVBOUcux1qlW8hfT6UPKGoVfYA==\n"}))
223
+ expect { Service.remote(:uploader, realm) }.to raise_error
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+
3
+ describe "Vidibus::Service::Error" do
4
+ it "should be derived from StandardError" do
5
+ Vidibus::Service::Error.superclass.should eql(StandardError)
6
+ end
7
+ end
8
+
9
+ describe "Service" do
10
+ it "should be a shorthand for Service.discover" do
11
+ mock(Service).discover(:uploader, "realm")
12
+ Service(:uploader, "realm")
13
+ end
14
+ end