end
# Remove any permission signatures from the manifest.
- resource_attrs[:manifest_text]
- .gsub!(/ [[:xdigit:]]{32}(\+[[:digit:]]+)?(\+\S+)/) { |word|
- word.strip!
- loc = Locator.parse(word)
- if loc
- " " + loc.without_signature.to_s
- else
- " " + word
- end
- }
+ munge_manifest_locators(resource_attrs[:manifest_text]) do |loc|
+ loc.without_signature.to_s
+ end
- # Save the collection with the stripped manifest.
- act_as_system_user do
- @object = model_class.new resource_attrs.reject { |k,v| k == :owner_uuid }
- begin
- @object.save!
- rescue ActiveRecord::RecordNotUnique
- logger.debug resource_attrs.inspect
- if @object.manifest_text and @object.uuid
- @existing_object = model_class.
- where('uuid=? and manifest_text=?',
- @object.uuid,
- @object.manifest_text).
- first
- @object = @existing_object || @object
- end
- end
- if @object
- link_attrs = {
- owner_uuid: owner_uuid,
- link_class: 'permission',
- name: 'can_read',
- head_uuid: @object.uuid,
- tail_uuid: owner_uuid
+ super
+ end
+
+ def find_object_by_uuid
+ if loc = Locator.parse(params[:id])
+ loc.strip_hints!
+ if c = Collection.readable_by(*@read_users).where({ portable_data_hash: loc.to_s }).limit(1).first
+ @object = {
+ portable_data_hash: c.portable_data_hash,
+ manifest_text: c.manifest_text,
+ files: c.files,
+ data_size: c.data_size
}
- ActiveRecord::Base.transaction do
- if Link.where(link_attrs).empty?
- Link.create! link_attrs
- end
- end
end
+ else
+ super
end
- show
+ true
end
def show
- if current_api_client_authorization
- signing_opts = {
- key: Rails.configuration.blob_signing_key,
- api_token: current_api_client_authorization.api_token,
- ttl: Rails.configuration.blob_signing_ttl,
- }
- @object[:manifest_text]
- .gsub!(/ [[:xdigit:]]{32}(\+[[:digit:]]+)?(\+\S+)/) { |word|
- word.strip!
- loc = Locator.parse(word)
- if loc
- " " + Blob.sign_locator(word, signing_opts)
- else
- " " + word
- end
- }
- end
- if @object.is_a? Collection
- render json: @object.as_api_response(:with_data)
- else
- render json: @object
- end
+ sign_manifests(@object[:manifest_text])
+ super
+ end
+
+ def index
+ sign_manifests(*@objects.map { |c| c[:manifest_text] })
+ super
end
- def collection_uuid(uuid)
- m = /([a-f0-9]{32}(\+[0-9]+)?)(\+.*)?/.match(uuid)
- if m
- m[1]
- else
- nil
- end
- end
-
def script_param_edges(visited, sp)
case sp
when Hash
api_accessible :user, extend: :common do |t|
t.add :data_size
t.add :files
+ t.add :name
+ t.add :description
+ t.add :properties
+ t.add :portable_data_hash
+ t.add :manifest_text
end
- api_accessible :with_data, extend: :user do |t|
- t.add :manifest_text
+ def self.attributes_required_columns
+ super.merge({ "data_size" => ["manifest_text"],
+ "files" => ["manifest_text"],
+ })
end
+ def set_portable_data_hash
+ if (self.portable_data_hash.nil? or (self.portable_data_hash == "") or (manifest_text_changed? and !portable_data_hash_changed?))
+ self.portable_data_hash = "#{Digest::MD5.hexdigest(manifest_text)}+#{manifest_text.length}"
+ elsif portable_data_hash_changed?
+ begin
+ loc = Locator.parse!(self.portable_data_hash)
+ loc.strip_hints!
+ self.portable_data_hash = loc.to_s
+ rescue ArgumentError => e
+ errors.add(:portable_data_hash, "#{e}")
+ return false
+ end
+ end
+ true
+ end
+
+ def ensure_hash_matches_manifest_text
+ if manifest_text_changed? or portable_data_hash_changed?
+ computed_hash = "#{Digest::MD5.hexdigest(manifest_text)}+#{manifest_text.length}"
+ unless computed_hash == portable_data_hash
+ logger.debug "(computed) '#{computed_hash}' != '#{portable_data_hash}' (provided)"
+ errors.add(:portable_data_hash, "does not match hash of manifest_text")
+ return false
+ end
+ end
+ true
+ end
+
def redundancy_status
if redundancy_confirmed_as.nil?
'unconfirmed'