ratom 0.5.0 → 0.5.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.
@@ -1,3 +1,7 @@
1
+ == 0.5.1 2008-08-05
2
+
3
+ * Added optional AuthHMAC support
4
+
1
5
  == 0.5.0 2008-07-28
2
6
 
3
7
  * Fix bug where processing instructions break parsing.
@@ -9,6 +9,7 @@ lib/atom.rb
9
9
  lib/atom/pub.rb
10
10
  lib/atom/version.rb
11
11
  lib/atom/xml/parser.rb
12
+ lib/atom/configuration.rb
12
13
  setup.rb
13
14
  spec/app/member_entry.atom
14
15
  spec/app/service.xml
data/README.txt CHANGED
@@ -215,7 +215,8 @@ We can tell rAtom about our custom namespace and custom class using the followin
215
215
  The first method call registers an alias for the "http://custom.namespace" namespace and the second method call
216
216
  tell rAtom that when it encounters a custom:property element within a Feed it should create an instance of Custom::Property
217
217
  and pass the XML Reader to the constructor of the instance. It is then up to the constructor to populate the objects attributes
218
- from the XML.
218
+ from the XML. Note that the alias you create using +add_extension_namespace+ can be anything you want, it doesn't need
219
+ to match the alias in the actual XML itself.
219
220
 
220
221
  The custom property will then be available as a method on the rAtom class. In the above example:
221
222
 
@@ -223,6 +224,11 @@ The custom property will then be available as a method on the rAtom class. In t
223
224
  @feed.custom_property.first.name == 'foo'
224
225
  @feed.custom_property.first.value == 'bar'
225
226
 
227
+ There is one caveat to this. By using this type of extension support you are permanently modifying the rAtom classes.
228
+ So if your application process one type of atom extension and you are happy with permanently modified rAtom classes,
229
+ the extra extensibility might work for you. If on the other hand you process lots of different types of extension you might
230
+ want to stick with simpler extension mechanism using the [namespace, element] method described above.
231
+
226
232
  (Thanks to nachokb for this feature!!)
227
233
 
228
234
  === Basic Authentication
@@ -246,6 +252,10 @@ method call that requires them. This might be a bit of a pain but it does make
246
252
  for protecting your credentials, although if you are using HTTP Basic Authentication there is a good chance your credentials aren't
247
253
  very well protected anyway.
248
254
 
255
+ === AuthHMAC authentication
256
+
257
+ As of version 0.5.1 rAtom also support authentication via HMAC request signing using the AuthHMAC[http://auth-hmac.rubyforge.org] gem. This is made available using the :hmac_access_id and :hmac_secret_key parameters which can be passed to the same methods as the HTTP Basic credentials support.
258
+
249
259
  == TODO
250
260
 
251
261
  * Support partial content responses from the server.
@@ -412,9 +412,9 @@ module Atom # :nodoc:
412
412
  end
413
413
 
414
414
  # Reloads the feed by fetching the self uri.
415
- def reload!
415
+ def reload!(opts = {})
416
416
  if links.self
417
- Feed.load_feed(URI.parse(links.self.href))
417
+ Feed.load_feed(URI.parse(links.self.href), opts)
418
418
  end
419
419
  end
420
420
 
@@ -545,9 +545,9 @@ module Atom # :nodoc:
545
545
  end
546
546
 
547
547
  # Reload the Entry by fetching the self link.
548
- def reload!
548
+ def reload!(opts = {})
549
549
  if links.self
550
- Entry.load_entry(URI.parse(links.self.href))
550
+ Entry.load_entry(URI.parse(links.self.href), opts)
551
551
  end
552
552
  end
553
553
  end
@@ -0,0 +1,24 @@
1
+ # Copyright (c) 2008 The Kaphan Foundation
2
+ #
3
+ # For licensing information see LICENSE.txt.
4
+ #
5
+ # Please visit http://www.peerworks.org/contact for further information.
6
+ #
7
+
8
+ module Atom
9
+ class Configuration
10
+ def self.auth_hmac_enabled?
11
+ unless defined?(@auth_hmac_enabled)
12
+ begin
13
+ gem 'auth-hmac'
14
+ require 'auth-hmac'
15
+ @auth_hmac_enabled = true
16
+ rescue
17
+ @auth_hmac_enabled = false
18
+ end
19
+ else
20
+ @auth_hmac_enabled
21
+ end
22
+ end
23
+ end
24
+ end
@@ -6,6 +6,7 @@
6
6
  #
7
7
 
8
8
  require 'atom'
9
+ require 'atom/configuration'
9
10
  require 'atom/xml/parser'
10
11
  require 'atom/version'
11
12
  require 'xml/libxml'
@@ -126,6 +127,12 @@ module Atom
126
127
  request = Net::HTTP::Post.new(uri.path, headers)
127
128
  if opts[:user] && opts[:pass]
128
129
  request.basic_auth(opts[:user], opts[:pass])
130
+ elsif opts[:hmac_access_id] && opts[:hmac_secret_key]
131
+ if Atom::Configuration.auth_hmac_enabled?
132
+ AuthHMAC.sign!(request, opts[:hmac_access_id], opts[:hmac_secret_key])
133
+ else
134
+ raise ArgumentError, "AuthHMAC credentials provides by auth-hmac gem is not installed"
135
+ end
129
136
  end
130
137
  response = http.request(request, entry.to_xml.to_s)
131
138
  end
@@ -171,7 +178,14 @@ module Atom
171
178
  request = Net::HTTP::Put.new(uri.path, headers)
172
179
  if opts[:user] && opts[:pass]
173
180
  request.basic_auth(opts[:user], opts[:pass])
181
+ elsif opts[:hmac_access_id] && opts[:hmac_secret_key]
182
+ if Atom::Configuration.auth_hmac_enabled?
183
+ AuthHMAC.sign!(request, opts[:hmac_access_id], opts[:hmac_secret_key])
184
+ else
185
+ raise ArgumentError, "AuthHMAC credentials provides by auth-hmac gem is not installed"
186
+ end
174
187
  end
188
+
175
189
  response = http.request(request, self.to_xml)
176
190
  end
177
191
 
@@ -193,7 +207,14 @@ module Atom
193
207
  request = Net::HTTP::Delete.new(uri.path, {'Accept' => 'application/atom+xml', 'User-Agent' => "rAtom #{Atom::VERSION::STRING}"})
194
208
  if opts[:user] && opts[:pass]
195
209
  request.basic_auth(opts[:user], opts[:pass])
210
+ elsif opts[:hmac_access_id] && opts[:hmac_secret_key]
211
+ if Atom::Configuration.auth_hmac_enabled?
212
+ AuthHMAC.sign!(request, opts[:hmac_access_id], opts[:hmac_secret_key])
213
+ else
214
+ raise ArgumentError, "AuthHMAC credentials provides by auth-hmac gem is not installed"
215
+ end
196
216
  end
217
+
197
218
  response = http.request(request)
198
219
  end
199
220
 
@@ -8,7 +8,7 @@ module Atom #:nodoc:
8
8
  module VERSION #:nodoc:
9
9
  MAJOR = 0
10
10
  MINOR = 5
11
- TINY = 0
11
+ TINY = 1
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY].join('.')
14
14
  end
@@ -271,6 +271,13 @@ module Atom
271
271
  request = Net::HTTP::Get.new(o.request_uri)
272
272
  if opts[:user] && opts[:pass]
273
273
  request.basic_auth(opts[:user], opts[:pass])
274
+ elsif opts[:hmac_access_id] && opts[:hmac_secret_key]
275
+ if Atom::Configuration.auth_hmac_enabled?
276
+ puts "Signing with HMAC"
277
+ AuthHMAC.sign!(request, opts[:hmac_access_id], opts[:hmac_secret_key])
278
+ else
279
+ raise ArgumentError, "AuthHMAC credentials provides by auth-hmac gem is not installed"
280
+ end
274
281
  end
275
282
  response = http.request(request)
276
283
  end
@@ -248,6 +248,27 @@ describe Atom::Pub do
248
248
  created = @collection.publish(entry, :user => 'user', :pass => 'pass')
249
249
  created.should == entry
250
250
  end
251
+
252
+ if Atom::Configuration.auth_hmac_enabled?
253
+ it "should send a POST with hmac authentication when an entry is published" do
254
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
255
+
256
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s)
257
+
258
+ http = mock('http')
259
+ http.should_receive(:request) do |request, entry_xml|
260
+ request['Authorization'].should match(/^AuthHMAC access_id:[a-zA-Z0-9\/+]+=*/)
261
+ response
262
+ end
263
+
264
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
265
+
266
+ created = @collection.publish(entry, :hmac_access_id => 'access_id', :hmac_secret_key => 'secret')
267
+ created.should == entry
268
+ end
269
+ else
270
+ xit "should send a POST with hmac authentication when an entry is published"
271
+ end
251
272
 
252
273
  it "should behave well when no content is returned" do
253
274
  entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
@@ -366,6 +387,23 @@ describe Atom::Pub do
366
387
  entry.save!(:user => 'user', :pass => 'pass')
367
388
  end
368
389
 
390
+ if Atom::Configuration.auth_hmac_enabled?
391
+ it "should send a PUT with hmac auth to the edit link on save!" do
392
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
393
+ response = mock_response(Net::HTTPSuccess, nil)
394
+
395
+ http = mock('http')
396
+ http.should_receive(:request) do |request, entry_xml|
397
+ request['Authorization'].should match(/^AuthHMAC access_id:[a-zA-Z0-9\/+]+=*$/)
398
+ response
399
+ end
400
+
401
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
402
+
403
+ entry.save!(:hmac_access_id => 'access_id', :hmac_secret_key => 'secret')
404
+ end
405
+ end
406
+
369
407
  it "should send a DELETE to the edit link on delete!" do
370
408
  entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
371
409
  response = mock_response(Net::HTTPSuccess, nil)
@@ -380,20 +418,37 @@ describe Atom::Pub do
380
418
  entry.destroy!
381
419
  end
382
420
 
383
- it "should send a DELETE to the edit link on delete!" do
421
+ it "should send a DELETE with basic auth to the edit link on delete!" do
422
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
423
+ response = mock_response(Net::HTTPSuccess, nil)
424
+
425
+ request = mock('request')
426
+ request.should_receive(:basic_auth).with('user', 'pass')
427
+ Net::HTTP::Delete.should_receive(:new).with('/member_entry.atom', an_instance_of(Hash)).and_return(request)
428
+
429
+ http = mock('http')
430
+ http.should_receive(:request).with(request).and_return(response)
431
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
432
+
433
+ entry.destroy!(:user => 'user', :pass => 'pass')
434
+ end
435
+
436
+ if Atom::Configuration.auth_hmac_enabled?
437
+ it "should send a DELETE with hmac auth to the edit link on delete!" do
384
438
  entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
385
439
  response = mock_response(Net::HTTPSuccess, nil)
386
440
 
387
- request = mock('request')
388
- request.should_receive(:basic_auth).with('user', 'pass')
389
- Net::HTTP::Delete.should_receive(:new).with('/member_entry.atom', an_instance_of(Hash)).and_return(request)
390
-
391
441
  http = mock('http')
392
- http.should_receive(:request).with(request).and_return(response)
442
+ http.should_receive(:request) do |request|
443
+ request['Authorization'].should match(/^AuthHMAC access_id:[a-zA-Z0-9\/+]+=*$/)
444
+ response
445
+ end
446
+
393
447
  Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
394
448
 
395
- entry.destroy!(:user => 'user', :pass => 'pass')
449
+ entry.destroy!(:hmac_access_id => 'access_id', :hmac_secret_key => 'secret')
396
450
  end
451
+ end
397
452
 
398
453
  it "should raise exception on save! without an edit link" do
399
454
  entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
@@ -143,9 +143,6 @@ describe Atom do
143
143
 
144
144
  lambda { Atom::Feed.load_feed(uri, :user => 'user', :pass => 'pass') }.should_not raise_error
145
145
  end
146
-
147
- it "should pass basic-auth credentials on the request" do
148
- end
149
146
  end
150
147
 
151
148
  describe 'Atom::Entry.load_entry' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ratom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peerworks
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2008-07-28 00:00:00 +09:30
13
+ date: 2008-08-11 00:00:00 +09:30
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -57,6 +57,7 @@ files:
57
57
  - lib/atom/pub.rb
58
58
  - lib/atom/version.rb
59
59
  - lib/atom/xml/parser.rb
60
+ - lib/atom/configuration.rb
60
61
  - setup.rb
61
62
  - spec/app/member_entry.atom
62
63
  - spec/app/service.xml