Rubocop WebDavRequest classes

This commit is contained in:
Brandon Robins
2017-12-27 17:46:14 -05:00
parent 87e901b6e6
commit 4d532e2c34
11 changed files with 175 additions and 61 deletions

View File

@@ -1,19 +1,24 @@
# frozen_string_literal: true
module Calligraphy
# Responsible for creating a duplicate of the source resource identified
# by the request to the destination resource identified by the URI in
# the Destination header.
class Copy < WebDavRequest
def request
# Executes the WebDAV request for a particular resource.
def execute
options = copy_move_options
can_copy = @resource.can_copy? options
if can_copy[:ancestor_exist]
return :precondition_failed
else
unless can_copy[:can_copy]
return :precondition_failed if can_copy[:ancestor_exist]
return :conflict
end unless can_copy[:can_copy]
end
return :locked if can_copy[:locked]
overwritten = @resource.copy options
return overwritten ? :no_content : :created
overwritten ? :no_content : :created
end
private

View File

@@ -1,6 +1,10 @@
# frozen_string_literal: true
module Calligraphy
# Responsible for deleting the resource identified by the request.
class Delete < WebDavRequest
def request
# Executes the WebDAV request for a particular resource.
def execute
return :locked if @resource.locked_to_user? @headers
if @resource.collection?
@@ -11,7 +15,7 @@ module Calligraphy
return :not_found unless @resource.exists?
end
return :no_content
:no_content
end
end
end

View File

@@ -1,11 +1,17 @@
# frozen_string_literal: true
module Calligraphy
# Responsible for retrieving whatever information is identified by the
# request.
class Get < WebDavRequest
def request(head: false)
# Executes the WebDAV request for a particular resource.
def execute(head: false)
if @resource.readable?
return :ok if head
return :ok, @resource.read
[:ok, @resource.read]
else
return :not_found
:not_found
end
end
end

View File

@@ -1,45 +1,53 @@
# frozen_string_literal: true
module Calligraphy
# Responsible for taking out a lock of any access type and refreshing
# existing locks.
class Lock < WebDavRequest
include Calligraphy::XML::Utils
def request
if @resource.request_body.blank? && !@resource.locked_to_user?(@headers)
attr_reader :resource_exists
def initialize(headers:, request:, response:, resource:)
super
# Determine is resource already exists before lock operation.
@resource_exists = @resource.exists?
end
# Executes the WebDAV request for a particular resource.
def execute
if refresh_lock?
lock_properties = @resource.refresh_lock
elsif (@resource.locked? && @resource.lock_is_exclusive?) ||
(@resource.locked_to_user?(@headers) && !xml_contains_shared_lock?)
elsif resource_locked?
return :locked
else
resource_exists_beforehand = @resource.exists?
# The `lockinfo` tag is used to specify the type of lock the client
# wishes to have created.
xml = xml_for body: body, node: 'lockinfo'
return :bad_request if xml == :bad_request
lock_properties = @resource.lock xml, @headers['Depth']
end
builder = xml_builder
xml_res = builder.lock_res lock_properties
lock_token = lock_properties[-1]
.select { |x| x.name == 'locktoken' }[0]
.children[0]
.text
response.headers['Lock-Token'] = "<#{lock_token}>"
set_xml_content_type
if resource_exists_beforehand
return :ok, xml_res
else
return :created, xml_res
end
build_response lock_properties
end
private
def refresh_lock?
@resource.request_body.blank? && !@resource.locked_to_user?(@headers)
end
def resource_locked?
(@resource.locked? && @resource.lock_is_exclusive?) ||
(@resource.locked_to_user?(@headers) && !xml_contains_shared_lock?)
end
def xml_contains_shared_lock?
lock_type = nil
xml = xml_for body: body, node: 'lockinfo'
xml.each do |node|
next unless node.is_a? Nokogiri::XML::Element
@@ -48,5 +56,33 @@ module Calligraphy
lock_type == 'shared'
end
def build_response(lock_properties)
builder = xml_builder
xml_res = builder.lock_res lock_properties
lock_token = extract_lock_token lock_properties
prepare_response_headers lock_token
response_status xml_res
end
def extract_lock_token(properties)
properties[-1]
.select { |x| x.name == 'locktoken' }[0]
.children[0]
.text
end
def prepare_response_headers(lock_token)
response.headers['Lock-Token'] = "<#{lock_token}>"
set_xml_content_type
end
def response_status(xml_res)
return :ok, xml_res if @resource_exists
[:created, xml_res]
end
end
end

View File

@@ -1,6 +1,11 @@
# frozen_string_literal: true
module Calligraphy
# Responsible for creating a new collection resource at the location
# specified by the request.
class Mkcol < WebDavRequest
def request
# Executes the WebDAV request for a particular resource.
def execute
return :method_not_allowed if @resource.exists?
return :conflict unless @resource.ancestor_exist?
return :unsupported_media_type unless @resource.request_body.blank?
@@ -8,7 +13,7 @@ module Calligraphy
@resource.create_collection
set_content_location_header
return :created
:created
end
private

View File

@@ -1,31 +1,56 @@
# frozen_string_literal: true
module Calligraphy
# Responsible for copying a resource then deleting the original source.
class Move < Copy
def request
# Executes the WebDAV request for a particular resource.
def execute
return :locked if @resource.locked_to_user? @headers
options = copy_move_options
if @resource.is_true? options[:overwrite]
to_path = options[:destination].tap { |s| s.slice! @resource.mount_point }
to_resource = @resource.class.new resource: to_path, req: @request, root_dir: @resource.root_dir
if to_resource.exists?
to_resource.delete_collection
to_resource_existed = true
end
previous_resource_existed = overwrite_destination
end
copy_status = super
return copy_status if [:precondition_failed, :conflict].include? copy_status
status = super
return status if %i[precondition_failed conflict].include? status
@resource.delete_collection
if copy_status == :created && to_resource_existed
return :no_content
else
response.headers['Location'] = options[:destination] if copy_status == :created
return copy_status
response_status status, previous_resource_existed
end
private
def options
copy_move_options
end
def overwrite_destination
to_path = options[:destination].tap { |s| s.slice! @resource.mount_point }
to_resource = destination_resource to_path
if to_resource.exists?
to_resource.delete_collection
previous_resource_existed = true
end
previous_resource_existed
end
def destination_resource(to_path)
@resource.class.new(
resource: to_path,
req: @request,
root_dir: @resource.root_dir
)
end
def response_status(status, previous_resource)
return :no_content if status == :created && previous_resource
response.headers['Location'] = options[:destination] if status == :created
status
end
end
end

View File

@@ -1,8 +1,12 @@
# frozen_string_literal: true
module Calligraphy
# Responsible for retrieving properties defined on the resource.
class Propfind < WebDavRequest
include Calligraphy::XML::Utils
def request
# Executes the WebDAV request for a particular resource.
def execute
xml = xml_for body: body, node: 'propfind'
return :bad_request if xml == :bad_request
@@ -12,7 +16,8 @@ module Calligraphy
xml_res = builder.propfind_res @resource.full_request_path, properties
set_xml_content_type
return :multi_status, xml_res
[:multi_status, xml_res]
end
end
end

View File

@@ -1,10 +1,17 @@
# frozen_string_literal: true
module Calligraphy
# Responsible for processing instructions specified in the request body
# to set and/or remove properties defined on the resource.
class Proppatch < WebDavRequest
include Calligraphy::XML::Utils
def request
# Executes the WebDAV request for a particular resource.
def execute
return :locked if @resource.locked_to_user? @headers
# The `propertyupdate` tag contains the request to alter properties
# on a resource.
xml = xml_for body: body, node: 'propertyupdate'
return :bad_request if xml == :bad_request
@@ -14,7 +21,8 @@ module Calligraphy
xml_res = builder.proppatch_res @resource.full_request_path, actions
set_xml_content_type
return :multi_status, xml_res
[:multi_status, xml_res]
end
end
end

View File

@@ -1,12 +1,16 @@
# frozen_string_literal: true
module Calligraphy
# Responsible for replacing the `Get` response entity of the resource.
class Put < WebDavRequest
def request
# Executes the WebDAV request for a particular resource.
def execute
return :locked if @resource.locked_to_user? @headers
return :method_not_allowed if @resource.collection?
@resource.write
return :created, @resource.contents
[:created, @resource.contents]
end
end
end

View File

@@ -1,6 +1,11 @@
# frozen_string_literal: true
module Calligraphy
# Responsible for removing the lock identified by the lock token in the
# request header.
class Unlock < WebDavRequest
def request
# Executes the WebDAV request for a particular resource.
def execute
return :bad_request if @headers['Lock-Token'].nil?
@resource.unlock lock_token_header

View File

@@ -1,4 +1,12 @@
# frozen_string_literal: true
module Calligraphy
# Base class for WebDavRequests.
#
# `WebDavRequest` exposes the `request` method, which is used by the
# `WebDavRequestsController` to execute the WebDAV request for a particular
# resource. This class also provides private methods for accessing the
# request body, setting response headers, and creating XML responses.
class WebDavRequest
attr_accessor :resource, :response
attr_reader :headers, :request
@@ -10,7 +18,8 @@ module Calligraphy
@resource = resource
end
def request
# Executes the WebDAV request for a particular resource.
def execute
raise NotImplemented
end
@@ -25,7 +34,9 @@ module Calligraphy
end
def xml_builder
Calligraphy::XML::Builder.new server_protocol: @request.env['SERVER_PROTOCOL']
protocol = @request.env['SERVER_PROTOCOL']
Calligraphy::XML::Builder.new server_protocol: protocol
end
end
end