thingfish 0.5.0.pre20160707192835 → 0.5.0.pre20161103181816

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1cb359c51a202a06ce18845971fb239473b3b52f
4
- data.tar.gz: 771be1e193d9d560f0669b8f5b2718684c673e70
3
+ metadata.gz: 74a092349d627e3de7578603e6cbba04c29f8045
4
+ data.tar.gz: eb4868b63ef6b8ad8b95c4ff5954f4482924bb3d
5
5
  SHA512:
6
- metadata.gz: 407d223a9dd672b39cea0e0d98222710835e65525d5e2011f5964a39cd1a9a3c58ab4aecea83ac591219ef9277be8a481179fc82fe825b6572ecc762fffe3991
7
- data.tar.gz: 4d58598b60d541b5e9deeeb1a7e06498c55e7828b8543f4baa0438c1a6b236ea61a993e2e041d5b4eb2a659463c15d7d081f16c99751b0650fa96bac186ee5ac
6
+ metadata.gz: 6e3a206fa9f2ad2dd07543f407f85972a42b4f073ae8cc3eab66ead4ec5947b74c6f4228741a96efdb15a22101c4251cc49cee7a6e4b5720a1bf5acefda41967
7
+ data.tar.gz: a923141975987b85e96e84bd20c017d06609110abf10e319bd76a61ef51be1f0b6e59e2c66d8bc5d3d4d0275c862d8a3826b2e6c17f844daf456d6b7cfb21d91
checksums.yaml.gz.sig ADDED
Binary file
data.tar.gz.sig ADDED
Binary file
data/Manifest.txt CHANGED
@@ -1,4 +1,6 @@
1
1
  .simplecov
2
+ ChangeLog
3
+ Gemfile
2
4
  History.rdoc
3
5
  LICENSE
4
6
  Manifest.txt
@@ -7,6 +9,7 @@ README.rdoc
7
9
  Rakefile
8
10
  bin/tfprocessord
9
11
  bin/thingfish
12
+ etc/mongrel2-config.rb
10
13
  etc/thingfish.conf.example
11
14
  lib/strelka/app/metadata.rb
12
15
  lib/strelka/httprequest/metadata.rb
@@ -20,6 +23,7 @@ lib/thingfish/metastore/memory.rb
20
23
  lib/thingfish/mixins.rb
21
24
  lib/thingfish/processor.rb
22
25
  lib/thingfish/processor/mp3.rb
26
+ lib/thingfish/processor/sha256.rb
23
27
  lib/thingfish/processordaemon.rb
24
28
  lib/thingfish/spechelpers.rb
25
29
  spec/data/APIC-1-image.mp3
@@ -35,5 +39,6 @@ spec/thingfish/metastore/memory_spec.rb
35
39
  spec/thingfish/metastore_spec.rb
36
40
  spec/thingfish/mixins_spec.rb
37
41
  spec/thingfish/processor/mp3_spec.rb
42
+ spec/thingfish/processor/sha256_spec.rb
38
43
  spec/thingfish/processor_spec.rb
39
44
  spec/thingfish_spec.rb
@@ -230,6 +230,7 @@ class Thingfish::Handler < Strelka::App
230
230
  :datastore => self.datastore.class.name
231
231
  }
232
232
 
233
+ self.check_resource_permissions( req )
233
234
  res.for( :text, :json, :yaml ) { info }
234
235
  return res
235
236
  end
@@ -244,6 +245,8 @@ class Thingfish::Handler < Strelka::App
244
245
  get do |req|
245
246
  finish_with HTTP::BAD_REQUEST, req.params.error_messages.join(', ') unless req.params.okay?
246
247
 
248
+ self.check_resource_permissions( req )
249
+
247
250
  uuids = self.metastore.search( req.params.valid )
248
251
  self.log.debug "UUIDs are: %p" % [ uuids ]
249
252
 
@@ -340,13 +343,15 @@ class Thingfish::Handler < Strelka::App
340
343
  metadata = self.metastore.fetch( uuid )
341
344
 
342
345
  finish_with HTTP::NOT_FOUND, "No such object." unless object && metadata
346
+ self.check_resource_permissions( req, nil, metadata )
343
347
 
344
348
  res = req.response
345
349
  res.content_type = metadata['format']
346
350
 
351
+ self.add_etag_headers( req, metadata )
352
+
347
353
  if object.respond_to?( :path )
348
354
  path = Pathname( object.path )
349
- self.log.debug "Server is chrooted to: %p" % [ req.server_chroot ]
350
355
  chroot_path = path.relative_path_from( req.server_chroot )
351
356
  res.extend_reply_with( :sendfile )
352
357
  res.headers.content_length = object.size
@@ -387,6 +392,7 @@ class Thingfish::Handler < Strelka::App
387
392
  self.datastore.include?( uuid ) or
388
393
  finish_with HTTP::NOT_FOUND, "No such object."
389
394
 
395
+ self.check_resource_permissions( req, uuid )
390
396
  self.remove_related_resources( uuid )
391
397
  self.save_resource( req, uuid )
392
398
  self.send_event( :replaced, :uuid => uuid )
@@ -403,6 +409,8 @@ class Thingfish::Handler < Strelka::App
403
409
  delete ':uuid' do |req|
404
410
  uuid = req.params[:uuid]
405
411
 
412
+ self.check_resource_permissions( req, uuid )
413
+
406
414
  self.datastore.remove( uuid ) or finish_with( HTTP::NOT_FOUND, "No such object." )
407
415
  metadata = self.metastore.remove( uuid )
408
416
  self.remove_related_resources( uuid )
@@ -433,9 +441,13 @@ class Thingfish::Handler < Strelka::App
433
441
 
434
442
  finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
435
443
 
444
+ metadata = self.metastore.fetch( uuid )
445
+ metadata[ 'oid' ] = uuid
446
+ self.check_resource_permissions( req, uuid, metadata )
447
+
436
448
  res = req.response
437
449
  res.status = HTTP::OK
438
- res.for( :json, :yaml ) { self.metastore.fetch( uuid ) }
450
+ res.for( :json, :yaml ) { metadata }
439
451
 
440
452
  return res
441
453
  end
@@ -449,9 +461,12 @@ class Thingfish::Handler < Strelka::App
449
461
 
450
462
  finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
451
463
 
464
+ metadata = self.metastore.fetch( uuid )
465
+ self.check_resource_permissions( req, uuid, metadata )
466
+
452
467
  res = req.response
453
468
  res.status = HTTP::OK
454
- res.for( :json, :yaml ) { self.metastore.fetch_value( uuid, key ) }
469
+ res.for( :json, :yaml ) { metadata[key] }
455
470
 
456
471
  return res
457
472
  end
@@ -467,6 +482,9 @@ class Thingfish::Handler < Strelka::App
467
482
  finish_with( HTTP::CONFLICT, "Key already exists." ) unless
468
483
  self.metastore.fetch_value( uuid, key ).nil?
469
484
 
485
+ metadata = self.metastore.fetch( uuid )
486
+ self.check_resource_permissions( req, uuid, metadata )
487
+
470
488
  self.metastore.merge( uuid, key => req.body.read )
471
489
  self.send_event( :metadata_updated, :uuid => uuid, :key => key )
472
490
 
@@ -490,6 +508,9 @@ class Thingfish::Handler < Strelka::App
490
508
  finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
491
509
  previous_value = self.metastore.fetch( uuid, key )
492
510
 
511
+ metadata = self.metastore.fetch( uuid )
512
+ self.check_resource_permissions( req, uuid, metadata )
513
+
493
514
  self.metastore.merge( uuid, key => req.body.read )
494
515
  self.send_event( :metadata_replaced, :uuid => uuid, :key => key )
495
516
 
@@ -514,6 +535,9 @@ class Thingfish::Handler < Strelka::App
514
535
 
515
536
  finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
516
537
 
538
+ metadata = self.metastore.fetch( uuid )
539
+ self.check_resource_permissions( req, uuid, metadata )
540
+
517
541
  op_metadata = self.metastore.fetch( uuid, *OPERATIONAL_METADATA_KEYS )
518
542
  new_metadata = self.extract_metadata( req )
519
543
  self.metastore.save( uuid, new_metadata.merge(op_metadata) )
@@ -533,6 +557,9 @@ class Thingfish::Handler < Strelka::App
533
557
 
534
558
  finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
535
559
 
560
+ metadata = self.metastore.fetch( uuid )
561
+ self.check_resource_permissions( req, uuid, metadata )
562
+
536
563
  new_metadata = self.extract_metadata( req )
537
564
  self.metastore.merge( uuid, new_metadata )
538
565
  self.send_event( :metadata_updated, :uuid => uuid )
@@ -551,6 +578,9 @@ class Thingfish::Handler < Strelka::App
551
578
 
552
579
  finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
553
580
 
581
+ metadata = self.metastore.fetch( uuid )
582
+ self.check_resource_permissions( req, uuid, metadata )
583
+
554
584
  self.metastore.remove_except( uuid, *OPERATIONAL_METADATA_KEYS )
555
585
  self.send_event( :metadata_deleted, :uuid => uuid )
556
586
 
@@ -571,6 +601,9 @@ class Thingfish::Handler < Strelka::App
571
601
  finish_with( HTTP::FORBIDDEN, "Protected metadata." ) if
572
602
  OPERATIONAL_METADATA_KEYS.include?( key )
573
603
 
604
+ metadata = self.metastore.fetch( uuid )
605
+ self.check_resource_permissions( req, uuid, metadata )
606
+
574
607
  self.metastore.remove( uuid, key )
575
608
  self.send_event( :metadata_deleted, :uuid => uuid, :key => key )
576
609
 
@@ -593,6 +626,9 @@ class Thingfish::Handler < Strelka::App
593
626
  metadata.merge!( self.extract_header_metadata(request) )
594
627
  metadata.merge!( self.extract_default_metadata(request) )
595
628
 
629
+ self.verify_operational_metadata( metadata )
630
+ self.check_resource_permissions( request, uuid, metadata )
631
+
596
632
  if uuid
597
633
  self.log.info "Replacing resource %s (encoding: %p)" %
598
634
  [ uuid, request.headers.content_encoding ]
@@ -714,6 +750,15 @@ class Thingfish::Handler < Strelka::App
714
750
  end
715
751
 
716
752
 
753
+ ### Check that the metadata provided contains valid values for
754
+ ### the operational keys, before saving a resource to disk.
755
+ def verify_operational_metadata( metadata )
756
+ if metadata.values_at( *OPERATIONAL_METADATA_KEYS ).any?( &:nil? )
757
+ finish_with( HTTP::BAD_REQUEST, "Missing operational attribute." )
758
+ end
759
+ end
760
+
761
+
717
762
  ### Send an event of +type+ with the given +msg+ over the zmq event socket.
718
763
  def send_event( type, msg )
719
764
  esock = self.event_socket or return
@@ -723,6 +768,30 @@ class Thingfish::Handler < Strelka::App
723
768
  end
724
769
 
725
770
 
771
+ ### Add browser cache headers for resources. This requires the sha256
772
+ ### processor plugin to be enabled for stored resources.
773
+ def add_etag_headers( request, metadata )
774
+ response = request.response
775
+ checksum = metadata[ 'checksum' ]
776
+ return unless checksum
777
+
778
+ if (( match = request.headers[ :if_none_match ] ))
779
+ match = match.gsub( '"', '' ).split( /,\s*/ )
780
+ finish_with( HTTP::NOT_MODIFIED ) if match.include?( checksum )
781
+ end
782
+
783
+ response.headers[ :etag ] = checksum
784
+ return
785
+ end
786
+
787
+
788
+ ### Supply a method that child handlers can override. The regular auth
789
+ ### plugin runs too early (but can also be used), this hook allows
790
+ ### child handlers to make access decisions based on the +request+
791
+ ### object, +uuid+ of the resource, or +metadata+ of the fetched resource.
792
+ def check_resource_permissions( request, uuid=nil, metadata=nil ); end
793
+
794
+
726
795
  end # class Thingfish::Handler
727
796
 
728
797
  # vim: set nosta noet ts=4 sw=4:
@@ -70,7 +70,9 @@ describe Thingfish::Handler do
70
70
 
71
71
 
72
72
  it 'accepts a POSTed upload' do
73
- req = factory.post( '/', TEST_TEXT_DATA, content_type: 'text/plain' )
73
+ req = factory.post( '/', TEST_TEXT_DATA )
74
+ req.content_type = 'text/plain'
75
+ req.headers.content_length = TEST_TEXT_DATA.bytesize
74
76
  res = @handler.handle( req )
75
77
 
76
78
  expect( res.status_line ).to match( /201 created/i )
@@ -145,6 +147,17 @@ describe Thingfish::Handler do
145
147
  end
146
148
 
147
149
 
150
+ it 'returns a BAD_REQUEST if unable to extract operational metadata' do
151
+ req = factory.post( '/', TEST_TEXT_DATA )
152
+ req.content_type = 'text/plain'
153
+
154
+ res = @handler.handle( req )
155
+ res.body.rewind
156
+ expect( res.status ).to be( HTTP::BAD_REQUEST )
157
+ expect( res.body.read ).to match( /missing operational attribute/i )
158
+ end
159
+
160
+
148
161
  it "allows additional metadata to be attached to uploads via X-Thingfish-* headers" do
149
162
  headers = {
150
163
  content_type: 'text/plain',
@@ -152,6 +165,7 @@ describe Thingfish::Handler do
152
165
  x_thingfish_tags: 'rapper,ukraine,potap',
153
166
  }
154
167
  req = factory.post( '/', TEST_TEXT_DATA, headers )
168
+ req.headers.content_length = TEST_TEXT_DATA.bytesize
155
169
  res = @handler.handle( req )
156
170
 
157
171
  expect( res.status_line ).to match( /201 created/i )
@@ -169,6 +183,7 @@ describe Thingfish::Handler do
169
183
  @handler.metastore.save( uuid, {'format' => 'text/plain'} )
170
184
 
171
185
  req = factory.put( "/#{uuid}", @png_io, content_type: 'image/png' )
186
+ req.headers.content_length = @png_io.read.bytesize
172
187
  res = @handler.handle( req )
173
188
 
174
189
  expect( res.status ).to eq( HTTP::NO_CONTENT )
@@ -182,6 +197,7 @@ describe Thingfish::Handler do
182
197
  @handler.metastore.save( uuid, {'format' => 'text/plain'} )
183
198
 
184
199
  req = factory.put( "/#{uuid.upcase}", @png_io, content_type: 'image/png' )
200
+ req.headers.content_length = @png_io.read.bytesize
185
201
  res = @handler.handle( req )
186
202
 
187
203
  expect( res.status ).to eq( HTTP::NO_CONTENT )
@@ -339,6 +355,32 @@ describe Thingfish::Handler do
339
355
  end
340
356
 
341
357
 
358
+ it "adds browser cache headers to resources with a checksum attribute" do
359
+ uuid = @handler.datastore.save( @png_io )
360
+ @handler.metastore.save( uuid, 'format' => 'image/png', 'checksum' => '123456' )
361
+
362
+ req = factory.get( "/#{uuid}" )
363
+ result = @handler.handle( req )
364
+
365
+ expect( result.status_line ).to match( /200 ok/i )
366
+ expect( result.headers.etag ).to eq( '123456' )
367
+ end
368
+
369
+
370
+ it "returns a 304 not modified for unchanged client cache requests" do
371
+ uuid = @handler.datastore.save( @png_io )
372
+ @handler.metastore.save( uuid, 'format' => 'image/png', 'checksum' => '123456' )
373
+
374
+ req = factory.get( "/#{uuid}" )
375
+ req.headers[ :if_none_match ] = '123456'
376
+ result = @handler.handle( req )
377
+
378
+ expect( result.status_line ).to match( /304 not modified/i )
379
+ expect( result.body.read ).to be_empty
380
+ end
381
+
382
+
383
+
342
384
  it "can remove everything associated with an object id" do
343
385
  uuid = @handler.datastore.save( @png_io )
344
386
  @handler.metastore.save( uuid, {
@@ -391,6 +433,7 @@ describe Thingfish::Handler do
391
433
  expect( result.status ).to eq( 200 )
392
434
  expect( result.headers.content_type ).to eq( 'application/json' )
393
435
  expect( content_hash ).to be_a( Hash )
436
+ expect( content_hash['oid'] ).to eq( uuid )
394
437
  expect( content_hash['extent'] ).to eq( 288 )
395
438
  expect( content_hash['created'] ).to eq( Time.at(1378313840).to_s )
396
439
  end
@@ -733,6 +776,7 @@ describe Thingfish::Handler do
733
776
  described_class.configure( :processors => %w[test] )
734
777
 
735
778
  req = factory.post( '/', TEST_TEXT_DATA, content_type: 'text/plain' )
779
+ req.headers.content_length = TEST_TEXT_DATA.bytesize
736
780
  res = @handler.handle( req )
737
781
  uuid = res.headers.x_thingfish_uuid
738
782
 
@@ -816,6 +860,7 @@ describe Thingfish::Handler do
816
860
 
817
861
  it "publishes notifications about uploaded assets to a PUBSUB socket" do
818
862
  req = factory.post( '/', TEST_TEXT_DATA, content_type: 'text/plain' )
863
+ req.headers.content_length = TEST_TEXT_DATA.bytesize
819
864
  res = @handler.handle( req )
820
865
 
821
866
  handles = ZMQ.select( [@subsock], nil, nil, 0 )
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thingfish
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0.pre20160707192835
4
+ version: 0.5.0.pre20161103181816
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
@@ -11,26 +11,32 @@ bindir: bin
11
11
  cert_chain:
12
12
  - |
13
13
  -----BEGIN CERTIFICATE-----
14
- MIIDMDCCAhigAwIBAgIBAjANBgkqhkiG9w0BAQUFADA+MQwwCgYDVQQDDANnZWQx
14
+ MIIEbDCCAtSgAwIBAgIBATANBgkqhkiG9w0BAQsFADA+MQwwCgYDVQQDDANnZWQx
15
15
  GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
16
- HhcNMTYwNjAyMDE1NTQ2WhcNMTcwNjAyMDE1NTQ2WjA+MQwwCgYDVQQDDANnZWQx
16
+ HhcNMTYwODIwMTgxNzQyWhcNMTcwODIwMTgxNzQyWjA+MQwwCgYDVQQDDANnZWQx
17
17
  GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
18
- ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDb92mkyYwuGBg1oRxt2tkH
19
- +Uo3LAsaL/APBfSLzy8o3+B3AUHKCjMUaVeBoZdWtMHB75X3VQlvXfZMyBxj59Vo
20
- cDthr3zdao4HnyrzAIQf7BO5Y8KBwVD+yyXCD/N65TTwqsQnO3ie7U5/9ut1rnNr
21
- OkOzAscMwkfQxBkXDzjvAWa6UF4c5c9kR/T79iA21kDx9+bUMentU59aCJtUcbxa
22
- 7kcKJhPEYsk4OdxR9q2dphNMFDQsIdRO8rywX5FRHvcb+qnXC17RvxLHtOjysPtp
23
- EWsYoZMxyCDJpUqbwoeiM+tAHoz2ABMv3Ahie3Qeb6+MZNAtMmaWfBx3dg2u+/WN
24
- AgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBSZ0hCV
25
- qoHr122fGKelqffzEQBhszANBgkqhkiG9w0BAQUFAAOCAQEAF2XCzjfTFxkcVvuj
26
- hhBezFkZnMDYtWezg4QCkR0RHg4sl1LdXjpvvI59SIgD/evD1hOteGKsXqD8t0E4
27
- OPAWWv/z+JRma72zeYsBZLSDRPIUvBoul6qCpvY0MiWTh496mFwOxT5lvSAUoh+U
28
- pQ/MQeH/yC6hbGp7IYska6J8T4z5XkYqafYZ3eKQ8H+xPd/z+gYx+jd0PfkWf1Wk
29
- QQdziL01SKBHf33OAH/p/puCpwS+ZDfgnNx5oMijWbc671UXkrt7zjD0kGakq+9I
30
- hnfm736z8j1wvWddqf45++gwPpDr1E4zoAq2PgRl/WBNyR0hfoZLpi3TnHu3eC0x
31
- uALKNA==
18
+ ggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC/JWGRHO+USzR97vXjkFgt
19
+ 83qeNf2KHkcvrRTSnR64i6um/ziin0I0oX23H7VYrDJC9A/uoUa5nGRJS5Zw/+wW
20
+ ENcvWVZS4iUzi4dsYJGY6yEOsXh2CcF46+QevV8iE+UmbkU75V7Dy1JCaUOyizEt
21
+ TH5UHsOtUU7k9TYARt/TgYZKuaoAMZZd5qyVqhF1vV+7/Qzmp89NGflXf2xYP26a
22
+ 4MAX2qqKX/FKXqmFO+AGsbwYTEds1mksBF3fGsFgsQWxftG8GfZQ9+Cyu2+l1eOw
23
+ cZ+lPcg834G9DrqW2zhqUoLr1MTly4pqxYGb7XoDhoR7dd1kFE2a067+DzWC/ADt
24
+ +QkcqWUm5oh1fN0eqr7NsZlVJDulFgdiiYPQiIN7UNsii4Wc9aZqBoGcYfBeQNPZ
25
+ soo/6za/bWajOKUmDhpqvaiRv9EDpVLzuj53uDoukMMwxCMfgb04+ckQ0t2G7wqc
26
+ /D+K9JW9DDs3Yjgv9k4h7YMhW5gftosd+NkNC/+Y2CkCAwEAAaN1MHMwCQYDVR0T
27
+ BAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFHKN/nkRusdqCJEuq3lgB3fJvyTg
28
+ MBwGA1UdEQQVMBOBEWdlZEBGYWVyaWVNVUQub3JnMBwGA1UdEgQVMBOBEWdlZEBG
29
+ YWVyaWVNVUQub3JnMA0GCSqGSIb3DQEBCwUAA4IBgQAPJzKiT0zBU7kpqe0aS2qb
30
+ FI0PJ4y5I8buU4IZGUD5NEt/N7pZNfOyBxkrZkXhS44Fp+xwBH5ebLbq/WY78Bqd
31
+ db0z6ZgW4LMYMpWFfbXsRbd9TU2f52L8oMAhxOvF7Of5qJMVWuFQ8FPagk2iHrdH
32
+ inYLQagqAF6goWTXgAJCdPd6SNeeSNqA6vlY7CV1Jh5kfNJJ6xu/CVij1GzCLu/5
33
+ DMOr26DBv+qLJRRC/2h34uX71q5QgeOyxvMg+7V3u/Q06DXyQ2VgeeqiwDFFpEH0
34
+ PFkdPO6ZqbTRcLfNH7mFgCBJjsfSjJrn0sPBlYyOXgCoByfZnZyrIMH/UY+lgQqS
35
+ 6Von1VDsfQm0eJh5zYZD64ZF86phSR7mUX3mXItwH04HrZwkWpvgd871DZVR3i1n
36
+ w8aNA5re5+Rt/Vvjxj5AcEnZnZiz5x959NaddQocX32Z1unHw44pzRNUur1GInfW
37
+ p4vpx2kUSFSAGjtCbDGTNV2AH8w9OU4xEmNz8c5lyoA=
32
38
  -----END CERTIFICATE-----
33
- date: 2016-07-08 00:00:00.000000000 Z
39
+ date: 2016-11-04 00:00:00.000000000 Z
34
40
  dependencies:
35
41
  - !ruby/object:Gem::Dependency
36
42
  name: strelka
@@ -103,47 +109,47 @@ dependencies:
103
109
  - !ruby/object:Gem::Version
104
110
  version: '0.2'
105
111
  - !ruby/object:Gem::Dependency
106
- name: rdoc
112
+ name: simplecov
107
113
  requirement: !ruby/object:Gem::Requirement
108
114
  requirements:
109
115
  - - "~>"
110
116
  - !ruby/object:Gem::Version
111
- version: '4.0'
117
+ version: '0.7'
112
118
  type: :development
113
119
  prerelease: false
114
120
  version_requirements: !ruby/object:Gem::Requirement
115
121
  requirements:
116
122
  - - "~>"
117
123
  - !ruby/object:Gem::Version
118
- version: '4.0'
124
+ version: '0.7'
119
125
  - !ruby/object:Gem::Dependency
120
- name: simplecov
126
+ name: ruby-mp3info
121
127
  requirement: !ruby/object:Gem::Requirement
122
128
  requirements:
123
129
  - - "~>"
124
130
  - !ruby/object:Gem::Version
125
- version: '0.7'
131
+ version: '0.8'
126
132
  type: :development
127
133
  prerelease: false
128
134
  version_requirements: !ruby/object:Gem::Requirement
129
135
  requirements:
130
136
  - - "~>"
131
137
  - !ruby/object:Gem::Version
132
- version: '0.7'
138
+ version: '0.8'
133
139
  - !ruby/object:Gem::Dependency
134
- name: ruby-mp3info
140
+ name: rdoc
135
141
  requirement: !ruby/object:Gem::Requirement
136
142
  requirements:
137
143
  - - "~>"
138
144
  - !ruby/object:Gem::Version
139
- version: '0.8'
145
+ version: '4.0'
140
146
  type: :development
141
147
  prerelease: false
142
148
  version_requirements: !ruby/object:Gem::Requirement
143
149
  requirements:
144
150
  - - "~>"
145
151
  - !ruby/object:Gem::Version
146
- version: '0.8'
152
+ version: '4.0'
147
153
  - !ruby/object:Gem::Dependency
148
154
  name: hoe
149
155
  requirement: !ruby/object:Gem::Requirement
@@ -237,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
237
243
  version: 1.3.1
238
244
  requirements: []
239
245
  rubyforge_project:
240
- rubygems_version: 2.4.8
246
+ rubygems_version: 2.5.1
241
247
  signing_key:
242
248
  specification_version: 4
243
249
  summary: Thingfish is a extensible, web-based digital asset manager
metadata.gz.sig ADDED
Binary file