Commits

Michael Granger committed bfee98f

Protect some basic metadata that's necessary for the service.

Comments (0)

Files changed (3)

 GET /v1/«uuid»/metadata/«key» *
 
 # append additional metadata for an asset
-POST /v1/«uuid»/metadata
+POST /v1/«uuid»/metadata *
 
 # add a value for an asset's specific metadata key
 POST /v1/«uuid»/metadata/«key»
 		metastore: 'memory'
 	}
 
+	# Metadata keys which aren't directly modifiable via the REST API
+	PROTECTED_METADATA_KEYS = %w[
+		format
+		extent
+	]
+
+
 	require 'thingfish/mixins'
 	require 'thingfish/datastore'
 	require 'thingfish/metastore'
 
 		finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
 
-		new_metadata = req.params.fields.dup
-		new_metadata.delete( :uuid )
-
+		new_metadata = self.extract_metadata( req )
 		self.metastore.merge( uuid, new_metadata )
 
 		res = req.response
 		}
 	end
 
+	### Extract and validate supplied metadata from the +request+.
+	def extract_metadata( req )
+		new_metadata = req.params.fields.dup
+		new_metadata.delete( :uuid )
+
+		protected_keys = PROTECTED_METADATA_KEYS & new_metadata.keys
+
+		unless protected_keys.empty?
+			finish_with HTTP::FORBIDDEN,
+				"Unable to alter protected metadata. (%s)" % [ protected_keys.join(', ') ]
+		end
+
+		return new_metadata
+	end
+
 end # class Thingfish
 
 # vim: set nosta noet ts=4 sw=4:

spec/thingfish_spec.rb

 			expect( handler.metastore.fetch(uuid, 'comment') ).to eq( 'Ignore me!' )
 		end
 
+
+		it "doesn't clobber protected metadata when merging metadata" do
+			uuid = handler.datastore.save( @png_io )
+			handler.metastore.save( uuid, {
+				'format' => 'image/png',
+				'extent' => 288,
+			})
+
+			body_json = Yajl.dump({ 'format' => 'text/plain', 'comment' => 'Ignore me!' })
+			req = factory.post( "/#{uuid}/metadata", body_json, 'Content-type' => 'application/json' )
+			result = handler.handle( req )
+
+			expect( result.status ).to eq( HTTP::FORBIDDEN )
+			expect( result.body.string ).to match( /unable to alter protected metadata/i )
+			expect( result.body.string ).to match( /format/i )
+			expect( handler.metastore.fetch(uuid, 'comment') ).to be_nil
+			expect( handler.metastore.fetch(uuid, 'format') ).to eq( 'image/png' )
+		end
+
 	end
 end