diff --git a/lib/dav4rack/resources/mongo_resource.rb b/lib/dav4rack/resources/mongo_resource.rb deleted file mode 100644 index 3ac6429c..00000000 --- a/lib/dav4rack/resources/mongo_resource.rb +++ /dev/null @@ -1,268 +0,0 @@ -# coding: utf-8 -# frozen_string_literal: true - -require 'mime/types' -require 'mongo' -require 'erb' -require 'dav4rack/security_utils' - -module DAV4Rack - - class MongoResource < DAV4Rack::Resource - - def self.database=(db) - @database = db - end - def self.database; @database end - - - def setup - @filesystem = Mongo::Grid::FSBucket.new(self.class.database) - if @options[:bson] - @bson = @options[:bson] - elsif path.empty? || path == '/' - @bson = {'filename' => '/'} - else - @bson = @filesystem.find(filename: /^#{Regexp.escape(path)}\/?$/).first rescue nil - end - end - - def child(bson) - our_options = @options.dup - @options[:bson] = bson - child = new_for_path bson['filename'] - @options = our_options - child - end - - # If this is a collection, return the child resources. - def children - @filesystem.find(filename: /^#{Regexp.escape(@bson['filename'])}[^\/]+\/?$/).map do |bson| - child bson - end - end - - # Is this resource a collection? - def collection? - @bson && _collection?(@bson['filename']) - end - - # Does this recource exist? - def exist? - !!@bson - end - - # Return the creation time. - def creation_date - @bson['uploadDate'] || Date.new - end - - # Return the time of last modification. - def last_modified - @bson['uploadDate'] || Date.new - end - - # Set the time of last modification. - def last_modified=(time) - end - - # Return an Etag, an unique hash value for this resource. - def etag - @bson['_id'].to_s - end - - # Return the mime type of this resource. - def content_type - @bson['contentType'] || "text/html" - end - - # Return the size in bytes for this resource. - def content_length - @bson['length'] || 0 - end - - # HTTP GET request. - # - # Write the content of the resource to the response.body. - def get(request, response) - return NotFound unless exist? - - if collection? - response.body = "".dup - response.body << "

" + ERB::Util.html_escape(path) + "

" - children.each do |child| - name = ERB::Util.html_escape child.name - - path = ERB::Util.html_escape request.path_for(child.path, - collection: child.collection?) - response.body << "" + name + "" - response.body << "
" - end - response.body << "" - response['Content-Type'] = 'text/html' - else - @filesystem.open_download_stream_by_name(path, revision: -1) do |s| - # not sure if the copying is necessary, but keeping the reference to - # s outside the block seems unsafe as we dont know if/when that - # stream will be closed - #response.body = s - response.body = s.read - response['Content-Type'] = @bson['contentType'] - end - end - OK - rescue Mongo::Error::InvalidFileRevision - NotFound - end - - # HTTP PUT request. - # - # Save the content of the request.body. - def put(request, response) - exists = exist? - - @filesystem.open_upload_stream( - path, content_type: content_type_for(path) - ) { |f| f.write request.body } - - exists ? NoContent : Created - end - - # HTTP POST request. - # - # Usually forbidden. - def post(request, response) - raise HTTPStatus::Forbidden - end - - # HTTP DELETE request. - # - # Delete this resource. - def delete - if collection? - @filesystem.find(filename: /^#{Regexp.escape(@bson['filename'])}/).each do |bson| - @filesystem.delete(bson['_id']) - end - else - @filesystem.delete(@bson['_id']) - end - NoContent - end - - # HTTP COPY request. - # - # Copy this resource to given destination path. - def copy(dest_path, overwrite = false, depth = :infinity) - dest = new_for_path dest_path - dest.collection! if collection? - - src = @bson['filename'] - dst = dest.path - exists = @filesystem.find(filename: /^#{Regexp.escape(dst)}/).any? - - if overwrite - @filesystem.find(filename: /^#{Regexp.escape(dst)}/).each do |bson| - @filesystem.delete bson['_id'] - end - elsif @filesystem.find(filename: /^#{Regexp.escape(dst)}/).any? - return PreconditionFailed - end - - @filesystem.find(filename: /^#{Regexp.escape(src)}/).each do |bson| - src_name = bson['filename'] - dst_name = dst + src_name.slice(src.length, src_name.length) - - @filesystem.open_download_stream_by_name(src_name) do |i| - @filesystem.open_upload_stream(dst_name, - content_type: bson['contentType']) do |o| - i.each{|chunk| o.write chunk } - end - end - end - - exists ? NoContent : Created - end - - # HTTP MOVE request. - # - # Move this resource to given destination path. - def move(dest_path, overwrite = false) - dest = new_for_path dest_path - dest.collection! if collection? - - src = @bson['filename'] - dst = dest.path - exists = @filesystem.find(filename: /^#{Regexp.escape(dst)}/).any? - - if overwrite - @filesystem.find(filename: /^#{Regexp.escape(dst)}/).each do |bson| - @filesystem.delete bson['_id'] - end - elsif @filesystem.find(filename: /^#{Regexp.escape(dst)}/).any? - return PreconditionFailed - end - - @filesystem.find(filename: /^#{Regexp.escape(src)}/).each do |bson| - src_name = bson['filename'] - dst_name = dst + src_name.slice(src.length, src_name.length) - - # http://mongoid.org/docs/persistence/atomic.html - # http://rubydoc.info/github/mongoid/mongoid/master/Mongoid/Collection#update-instance_method - mongo_collection.find_one_and_update({'_id' => bson['_id']}, {'$set' => {'filename' => dst_name}}, safe: true) - - end - - exists ? NoContent : Created - end - - # HTTP MKCOL request. - # - # Create this resource as collection. - def make_collection - - if @filesystem.find(filename: path).any? - raise 'resource exists' - end - collection! - @filesystem.open_upload_stream(path) { |f| } - - Created - end - - def collection! - path << '/' unless _collection?(path) - end - - def authenticate(user, pass) - if(@options[:username]) - # This comparison uses & so that it doesn't short circuit and - # uses `variable_size_secure_compare` so that length information - # isn't leaked. - SecurityUtils.variable_size_secure_compare( - user, @options[:username] - ) & - SecurityUtils.variable_size_secure_compare( - pass, @options[:password] - ) - else - true - end - end - - private - - def mongo_collection - @mongo_collection ||= self.class.database['fs.files'] - end - - def content_type_for(filename) - MIME::Types.type_for(filename).first.to_s || 'text/html' - end - - def _collection?(path) - path && path.end_with?('/') - end - - end - -end