Dav4rack library upgraded to the latest stable version
This commit is contained in:
parent
1d53518eaa
commit
5ca5331d4d
@ -1,8 +1,8 @@
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
|
||||
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2011-14 Karel Pičman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@ -22,12 +22,12 @@ module RedmineDmsf
|
||||
module Test
|
||||
class IntegrationTest < ActionController::IntegrationTest
|
||||
def self.fixtures(*table_names)
|
||||
dir = File.join(File.dirname(__FILE__), '../../../test/fixtures')
|
||||
modified_tables = table_names.reject{|x| !File.exist?("#{dir}/#{x}.yml") }
|
||||
ActiveRecord::Fixtures.create_fixtures(dir, modified_tables) unless modified_tables.empty?
|
||||
table_names -= modified_tables
|
||||
super(table_names-modified_tables)
|
||||
dir = File.join( File.dirname(__FILE__), '../../../test/fixtures')
|
||||
table_names.each do |x|
|
||||
ActiveRecord::Fixtures.create_fixtures(dir, x) if File.exist?("#{dir}/#{x}.yml")
|
||||
end
|
||||
super(table_names)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,8 +1,8 @@
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
|
||||
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2011-14 Karel Pičman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@ -27,9 +27,9 @@ module RedmineDmsf
|
||||
# and allowing us to suppliment redmine fixtures if we need to.
|
||||
def self.fixtures(*table_names)
|
||||
dir = File.join( File.dirname(__FILE__), '../../../test/fixtures')
|
||||
table_names.each{|x|
|
||||
table_names.each do |x|
|
||||
ActiveRecord::Fixtures.create_fixtures(dir, x) if File.exist?("#{dir}/#{x}.yml")
|
||||
}
|
||||
end
|
||||
super(table_names)
|
||||
end
|
||||
|
||||
@ -40,4 +40,4 @@ module RedmineDmsf
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,8 +1,8 @@
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2013 Karel Pičman <karel.picman@kontron.com>
|
||||
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2011-14 Karel Pičman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@ -31,16 +31,13 @@ module RedmineDmsf
|
||||
# Allow us to override the fixtures method to implement fixtures for our plugin.
|
||||
# Ultimately it allows for better integration without blowing redmine fixtures up,
|
||||
# and allowing us to suppliment redmine fixtures if we need to.
|
||||
def self.fixtures(*table_names)
|
||||
dir = File.expand_path('../../../../test/fixtures', __FILE__)
|
||||
def self.fixtures(*table_names)
|
||||
dir = File.join( File.dirname(__FILE__), '../../../test/fixtures')
|
||||
table_names.each do |x|
|
||||
if File.exist?("#{dir}/#{x}.yml")
|
||||
ActiveRecord::Fixtures.create_fixtures(dir, x)
|
||||
end
|
||||
ActiveRecord::Fixtures.create_fixtures(dir, x) if File.exist?("#{dir}/#{x}.yml")
|
||||
end
|
||||
super(table_names)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,6 +1,7 @@
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2011-14 Karel Picman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@ -25,7 +26,7 @@ module RedmineDmsf
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
def initialize(*args)
|
||||
webdav_setting = Setting.plugin_redmine_dmsf["dmsf_webdav"]
|
||||
webdav_setting = Setting.plugin_redmine_dmsf['dmsf_webdav']
|
||||
raise NotFound if !webdav_setting.nil? && webdav_setting.empty?
|
||||
super(*args)
|
||||
end
|
||||
@ -66,7 +67,7 @@ module RedmineDmsf
|
||||
'',
|
||||
'',
|
||||
] + entities unless parent.nil?
|
||||
@response.body << index_page % [ path.empty? ? "/" : path, path.empty? ? "/" : path , entities ]
|
||||
@response.body << index_page % [ path.empty? ? '/' : path, path.empty? ? '/' : path , entities ]
|
||||
end
|
||||
|
||||
#Run method through proxy class - ensuring always compatible child is generated
|
||||
@ -133,7 +134,7 @@ table { width:100%%; }
|
||||
|
||||
#Make it easy to find the path without project in it.
|
||||
def projectless_path
|
||||
'/'+path.split('/').drop(2).join('/')
|
||||
'/' + path.split('/').drop(2).join('/')
|
||||
end
|
||||
|
||||
def path_prefix
|
||||
@ -141,6 +142,4 @@ table { width:100%%; }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@ -22,51 +22,39 @@ require 'dav4rack'
|
||||
module RedmineDmsf
|
||||
module Webdav
|
||||
class Controller < DAV4Rack::Controller
|
||||
include DAV4Rack::Utils
|
||||
|
||||
# Overload default options
|
||||
def options
|
||||
raise NotFound unless resource.exist?
|
||||
response['Allow'] = 'OPTIONS,HEAD,GET,PUT,POST,DELETE,PROPFIND,PROPPATCH,MKCOL,COPY,MOVE,LOCK,UNLOCK'
|
||||
response['Dav'] = '1,2,3'
|
||||
response['Ms-Author-Via'] = 'DAV'
|
||||
OK
|
||||
end
|
||||
|
||||
# This is just pain DIRTY
|
||||
# to fix some gem bugs we're overriding their controller
|
||||
def lock
|
||||
begin
|
||||
request.env['Timeout'] = request.env['HTTP_TIMEOUT'].split('-',2).join(',') unless request.env['HTTP_TIMEOUT'].nil?
|
||||
rescue
|
||||
# Nothing here
|
||||
end
|
||||
|
||||
request_document.remove_namespaces! if ns.empty?
|
||||
# We re-imlement the function ns - if its return is empty, there are no usable namespaces
|
||||
# so to prevent never returning data, we stip all namespaces
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
|
||||
# Overload the default propfind function with this
|
||||
# Return response to PROPFIND
|
||||
def propfind
|
||||
unless(resource.exist?)
|
||||
NotFound
|
||||
else
|
||||
unless(request_document.xpath("//#{ns}propfind/#{ns}allprop").empty?)
|
||||
names = resource.property_names
|
||||
# Win7 hack start
|
||||
#unless(request_document.xpath("//#{ns}propfind/#{ns}allprop").empty?)
|
||||
# properties = resource.properties
|
||||
if request_document.xpath("//#{ns}propfind").empty? || request_document.xpath("//#{ns}propfind/#{ns}allprop").present?
|
||||
properties = resource.properties.map { |prop| DAV4Rack::DAVElement.new(prop.merge(:namespace => DAV4Rack::DAVElement.new(:href => prop[:ns_href]))) }
|
||||
# Win7 hack end
|
||||
else
|
||||
names = (
|
||||
ns.empty? ? request_document.remove_namespaces! : request_document
|
||||
).xpath(
|
||||
"//#{ns}propfind/#{ns}prop"
|
||||
).children.find_all{ |item|
|
||||
item.element? && item.name.start_with?(ns)
|
||||
}.map{ |item|
|
||||
item.name.sub("#{ns}::", '')
|
||||
}
|
||||
names = resource.property_names if names.empty?
|
||||
check = request_document.xpath("//#{ns}propfind")
|
||||
if(check && !check.empty?)
|
||||
properties = request_document.xpath(
|
||||
"//#{ns}propfind/#{ns}prop"
|
||||
).children.find_all{ |item|
|
||||
item.element?
|
||||
}.map{ |item|
|
||||
# We should do this, but Nokogiri transforms prefix w/ null href into
|
||||
# something valid. Oops.
|
||||
# TODO: Hacky grep fix that's horrible
|
||||
hsh = to_element_hash(item)
|
||||
if(hsh.namespace.nil? && !ns.empty?)
|
||||
raise BadRequest if request_document.to_s.scan(%r{<#{item.name}[^>]+xmlns=""}).empty?
|
||||
end
|
||||
hsh
|
||||
}.compact
|
||||
else
|
||||
raise BadRequest
|
||||
end
|
||||
end
|
||||
multistatus do |xml|
|
||||
find_resources.each do |resource|
|
||||
@ -76,54 +64,53 @@ module RedmineDmsf
|
||||
else
|
||||
xml.href url_format(resource)
|
||||
end
|
||||
propstats(xml, get_properties(resource, names))
|
||||
propstats(xml, get_properties(resource, properties.empty? ? resource.properties : properties))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# root_type:: Root tag name
|
||||
# Render XML and set Rack::Response#body= to final XML
|
||||
# Another override (they don't seem to flag UTF-8 [at this point I'm considering forking the gem to fix,
|
||||
# and making DMSF compliant on that .. *sigh*
|
||||
def render_xml(root_type)
|
||||
raise ArgumentError.new 'Expecting block' unless block_given?
|
||||
doc = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml_base|
|
||||
xml_base.send(root_type.to_s, {'xmlns:D' => 'DAV:'}.merge(resource.root_xml_attributes)) do
|
||||
xml_base.parent.namespace = xml_base.parent.namespace_definitions.first
|
||||
xml = xml_base['D']
|
||||
yield xml
|
||||
|
||||
# args:: Only argument used: :copy
|
||||
# Move Resource to new location. If :copy is provided,
|
||||
# Resource will be copied (implementation ease)
|
||||
# The only reason for overriding is a typing mistake 'include' -> 'include?'!
|
||||
def move(*args)
|
||||
unless(resource.exist?)
|
||||
NotFound
|
||||
else
|
||||
resource.lock_check if resource.supports_locking? && !args.include?(:copy)
|
||||
destination = url_unescape(env['HTTP_DESTINATION'].sub(%r{https?://([^/]+)}, ''))
|
||||
dest_host = $1
|
||||
if(dest_host && dest_host.gsub(/:\d{2,5}$/, '') != request.host)
|
||||
BadGateway
|
||||
elsif(destination == resource.public_path)
|
||||
Forbidden
|
||||
else
|
||||
collection = resource.collection?
|
||||
dest = resource_class.new(destination, clean_path(destination), @request, @response, @options.merge(:user => resource.user))
|
||||
status = nil
|
||||
if(args.include?(:copy))
|
||||
status = resource.copy(dest, overwrite)
|
||||
else
|
||||
return Conflict unless depth.is_a?(Symbol) || depth > 1
|
||||
status = resource.move(dest, overwrite)
|
||||
end
|
||||
response['Location'] = "#{scheme}://#{host}:#{port}#{url_format(dest)}" if status == Created
|
||||
# RFC 2518
|
||||
if collection
|
||||
multistatus do |xml|
|
||||
xml.response do
|
||||
xml.href "#{scheme}://#{host}:#{port}#{url_format(status == Created ? dest : resource)}"
|
||||
xml.status "#{http_version} #{status.status_line}"
|
||||
end
|
||||
end
|
||||
else
|
||||
status
|
||||
end
|
||||
end
|
||||
end
|
||||
response.body = doc.to_xml
|
||||
response['Content-Type'] = 'application/xml; charset="utf-8"'
|
||||
response['Content-Length'] = response.body.bytesize.to_s
|
||||
end
|
||||
|
||||
# Returns Resource path with root URI removed
|
||||
def implied_path
|
||||
|
||||
return clean_path(@request.path_info.dup) unless @request.path_info.empty?
|
||||
c_path = clean_path(@request.path.dup)
|
||||
return c_path if c_path.length != @request.path.length
|
||||
|
||||
# If we're here then it's probably down to thin
|
||||
return @request.path.dup.gsub!(/^#{Regexp.escape(@request.script_name)}/, '') unless @request.script_name.empty?
|
||||
|
||||
return c_path # This will probably result in a processing error if we hit here
|
||||
end
|
||||
|
||||
private
|
||||
def ns(opt_head = '')
|
||||
_ns = opt_head
|
||||
if(request_document && request_document.root && request_document.root.namespace_definitions.size > 0)
|
||||
_ns = request_document.root.namespace_definitions.first.prefix.to_s
|
||||
_ns += ':' unless _ns.empty?
|
||||
end
|
||||
_ns.empty? ? opt_head : _ns
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,6 +1,7 @@
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2011-14 Karel Picman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@ -37,9 +38,9 @@ module RedmineDmsf
|
||||
before do |resource, method_name|
|
||||
#If our method is not one of the following, there is no point continuing.
|
||||
if [ :put, :make_collection, :move, :copy, :delete, :lock, :unlock, :set_property ].include?(method_name)
|
||||
webdav_setting = Setting.plugin_redmine_dmsf["dmsf_webdav_strategy"]
|
||||
webdav_setting = "WEBDAV_READ_ONLY" if webdav_setting.nil?
|
||||
raise BadGateway if webdav_setting == "WEBDAV_READ_ONLY"
|
||||
webdav_setting = Setting.plugin_redmine_dmsf['dmsf_webdav_strategy']
|
||||
webdav_setting = 'WEBDAV_READ_ONLY' unless webdav_setting
|
||||
raise BadGateway if webdav_setting == 'WEBDAV_READ_ONLY'
|
||||
end
|
||||
end
|
||||
|
||||
@ -48,7 +49,7 @@ module RedmineDmsf
|
||||
# Our already quite heavy usage of DB would just get silly every time we called
|
||||
# this method.
|
||||
def children
|
||||
return @children unless @children.nil?
|
||||
return @children if @children
|
||||
@children = []
|
||||
return [] unless collection?
|
||||
folder.subfolders.map do |p|
|
||||
@ -83,15 +84,15 @@ module RedmineDmsf
|
||||
# Note: Folder is searched for as a generic search to prevent SQL queries being generated:
|
||||
# if we were to look within parent, we'd have to go all the way up the chain as part of the
|
||||
# existence check, and although I'm sure we'd love to access the heirarchy, I can't yet
|
||||
# see a practical need for it
|
||||
folders = DmsfFolder.visible.find(:all, :conditions => ["project_id = :project_id AND title = :title", {:project_id => project.id, :title => basename}], :order => "title ASC")
|
||||
# see a practical need for it
|
||||
folders = DmsfFolder.visible.where(:project_id => project.id, :title => basename).order('title ASC').all
|
||||
return nil unless folders.length > 0
|
||||
if (folders.length > 1) then
|
||||
folders.delete_if {|x| '/'+x.dmsf_path_str != projectless_path}
|
||||
folders.delete_if { |x| '/' + x.dmsf_path_str != projectless_path }
|
||||
return nil unless folders.length > 0
|
||||
@folder = folders[0]
|
||||
else
|
||||
if ('/'+folders[0].dmsf_path_str == projectless_path) then
|
||||
if ('/' + folders[0].dmsf_path_str == projectless_path) then
|
||||
@folder = folders[0]
|
||||
end
|
||||
end
|
||||
@ -108,12 +109,12 @@ module RedmineDmsf
|
||||
# Todo: Move file data retrieval into folder function, and use file method to determine existence
|
||||
def file
|
||||
return @file unless @file == false
|
||||
return nil if project.nil? || project.id.nil? #Again if entity project is nil, it cannot exist in context of this object
|
||||
return nil if project.nil? || project.id.nil? # Again if entity project is nil, it cannot exist in context of this object
|
||||
@file = nil
|
||||
|
||||
# Hunt for files parent path
|
||||
f = false
|
||||
if (parent.projectless_path != "/")
|
||||
if (parent.projectless_path != '/')
|
||||
if parent.folder?
|
||||
f = parent.folder
|
||||
end
|
||||
@ -129,8 +130,8 @@ module RedmineDmsf
|
||||
# If folder is false, means it couldn't pick up parent,
|
||||
# as such its probably fine to bail out, however we'll
|
||||
# perform a search in this scenario
|
||||
files = DmsfFile.visible.find(:all, :conditions => ["project_id = :project_id AND name = :file_name", {:project_id => project.id, :file_name => basename}], :order => "name ASC")
|
||||
files.delete_if {|x| File.dirname('/'+x.dmsf_path_str) != File.dirname(projectless_path)}
|
||||
files = DmsfFile.visible.where(:project_id => project.id, :name => basename).order('name ASC').all
|
||||
files.delete_if {|x| File.dirname('/' + x.dmsf_path_str) != File.dirname(projectless_path)}
|
||||
if files.length > 0
|
||||
@file = files[0]
|
||||
end
|
||||
@ -146,7 +147,7 @@ module RedmineDmsf
|
||||
# will return inode/directory for any collections, and appropriate for File entities
|
||||
def content_type
|
||||
if folder? then
|
||||
"inode/directory"
|
||||
'inode/directory'
|
||||
elsif file?
|
||||
file.last_revision.detect_content_type
|
||||
else
|
||||
@ -200,7 +201,7 @@ module RedmineDmsf
|
||||
response['Content-Length'] = response.body.bytesize.to_s
|
||||
else
|
||||
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:view_dmsf_files, project)
|
||||
response.body = download #Rack based provider
|
||||
response.body = download # Rack based provider
|
||||
end
|
||||
OK
|
||||
end
|
||||
@ -233,12 +234,12 @@ module RedmineDmsf
|
||||
# <instance> should be of entity to be deleted, we simply follow the Dmsf entity method
|
||||
# for deletion and return of appropriate status based on outcome.
|
||||
def delete
|
||||
if(file?) then
|
||||
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_manipulation, project)
|
||||
file.delete ? NoContent : Conflict
|
||||
elsif (folder?) then
|
||||
if file
|
||||
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_delete, project)
|
||||
file.delete(false) ? NoContent : Conflict
|
||||
elsif folder
|
||||
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:folder_manipulation, project)
|
||||
folder.delete ? NoContent : Conflict
|
||||
folder.delete(false) ? NoContent : Conflict
|
||||
else
|
||||
MethodNotAllowed
|
||||
end
|
||||
@ -274,7 +275,7 @@ module RedmineDmsf
|
||||
|
||||
else
|
||||
|
||||
if(parent.projectless_path == "/") #Project root
|
||||
if(parent.projectless_path == '/') #Project root
|
||||
folder.dmsf_folder_id = nil
|
||||
else
|
||||
return PreconditionFailed unless parent.exist? && parent.folder?
|
||||
@ -298,7 +299,7 @@ module RedmineDmsf
|
||||
|
||||
else
|
||||
|
||||
if(parent.projectless_path == "/") #Project root
|
||||
if(parent.projectless_path == '/') #Project root
|
||||
f = nil
|
||||
else
|
||||
return PreconditionFailed unless parent.exist? && parent.folder?
|
||||
@ -377,7 +378,7 @@ module RedmineDmsf
|
||||
User.current.allowed_to?(:view_dmsf_files, resource.project) &&
|
||||
User.current.allowed_to?(:view_dmsf_files, project))
|
||||
|
||||
if(parent.projectless_path == "/") #Project root
|
||||
if(parent.projectless_path == '/') #Project root
|
||||
f = nil
|
||||
else
|
||||
return PreconditionFailed unless parent.exist? && parent.folder?
|
||||
@ -431,7 +432,7 @@ module RedmineDmsf
|
||||
|
||||
http_if = http_if.slice(1, http_if.length - 2)
|
||||
l = DmsfLock.find(http_if)
|
||||
return Conflict if l.nil?
|
||||
return Conflict unless l
|
||||
l.expires_at = Time.now + 1.hour
|
||||
l.save!
|
||||
@response['Lock-Token'] = l.uuid
|
||||
@ -442,8 +443,8 @@ module RedmineDmsf
|
||||
return Conflict
|
||||
end
|
||||
|
||||
scope = "scope_#{(args[:scope] || "exclusive")}".to_sym
|
||||
type = "type_#{(args[:type] || "write")}".to_sym
|
||||
scope = "scope_#{(args[:scope] || 'exclusive')}".to_sym
|
||||
type = "type_#{(args[:type] || 'write')}".to_sym
|
||||
|
||||
#l should be the instance of the lock we've just created
|
||||
l = entity.lock!(scope, type, Time.now + 1.hours)
|
||||
@ -468,7 +469,7 @@ module RedmineDmsf
|
||||
entity = file? ? file : folder
|
||||
l = DmsfLock.find(token)
|
||||
l_entity = l.file || l.folder
|
||||
# Additional case: if a user trys to unlock the file instead of the folder that's locked
|
||||
# Additional case: if a user tries to unlock the file instead of the folder that's locked
|
||||
# This should throw forbidden as only the lock at level initiated should be unlocked
|
||||
if (!entity.locked? || entity.locked_for_user? || l_entity != entity)
|
||||
Forbidden
|
||||
@ -497,7 +498,7 @@ module RedmineDmsf
|
||||
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_manipulation, project)
|
||||
|
||||
new_revision = DmsfFileRevision.new
|
||||
if (exist? && file?) #We're over-writing something, so ultimately a new revision
|
||||
if (exist? && file?) # We're over-writing something, so ultimately a new revision
|
||||
f = file
|
||||
last_revision = file.last_revision
|
||||
new_revision.source_revision = last_revision
|
||||
@ -505,12 +506,12 @@ module RedmineDmsf
|
||||
new_revision.minor_version = last_revision.minor_version
|
||||
new_revision.workflow = last_revision.workflow
|
||||
else
|
||||
raise BadRequest unless ( parent.projectless_path == "/" || (parent.exist? && parent.folder?) )
|
||||
raise BadRequest unless ( parent.projectless_path == '/' || (parent.exist? && parent.folder?) )
|
||||
f = DmsfFile.new
|
||||
f.project = project
|
||||
f.name = basename
|
||||
f.folder = parent.folder
|
||||
f.notification = !Setting.plugin_redmine_dmsf["dmsf_default_notifications"].blank?
|
||||
f.notification = !Setting.plugin_redmine_dmsf['dmsf_default_notifications'].blank?
|
||||
new_revision.minor_version = 0
|
||||
new_revision.major_version = 0
|
||||
end
|
||||
@ -533,7 +534,7 @@ module RedmineDmsf
|
||||
elsif request.body.respond_to? 'size'
|
||||
new_revision.size = request.body.size
|
||||
else
|
||||
new_revision.size = request.content_length #Bad Guess
|
||||
new_revision.size = request.content_length # Bad Guess
|
||||
end
|
||||
raise InternalServerError unless new_revision.valid? && f.save
|
||||
new_revision.disk_filename = new_revision.new_storage_filename
|
||||
@ -551,16 +552,20 @@ module RedmineDmsf
|
||||
# get_property
|
||||
# Overriding the base definition (extending it really) with functionality
|
||||
# for lock information to be presented
|
||||
def get_property(name)
|
||||
case name
|
||||
def get_property(element)
|
||||
raise NotImplemented if (element[:ns_href] != 'DAV:')
|
||||
case element[:name]
|
||||
when 'supportedlock' then supported_lock
|
||||
when 'lockdiscovery' then discover_lock
|
||||
else super
|
||||
end
|
||||
end
|
||||
|
||||
def property_names
|
||||
%w(creationdate displayname getlastmodified getetag resourcetype getcontenttype getcontentlength supportedlock lockdiscovery)
|
||||
|
||||
# Available properties
|
||||
def properties
|
||||
%w(creationdate displayname getlastmodified getetag resourcetype getcontenttype getcontentlength supportedlock lockdiscovery).collect do |prop|
|
||||
{:name => prop, :ns_href => 'DAV:'}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@ -97,4 +97,4 @@ module RedmineDmsf
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -54,6 +54,10 @@ module RedmineDmsf
|
||||
return !User.current.anonymous? unless User.current.nil?
|
||||
false
|
||||
end
|
||||
|
||||
def supports_locking?
|
||||
true
|
||||
end
|
||||
|
||||
def children
|
||||
@resource_c.children
|
||||
@ -94,7 +98,43 @@ module RedmineDmsf
|
||||
def get(request, response)
|
||||
@resource_c.get(request, response)
|
||||
end
|
||||
|
||||
def put(request, response)
|
||||
@resource_c.put(request, response)
|
||||
end
|
||||
|
||||
def delete
|
||||
@resource_c.delete
|
||||
end
|
||||
|
||||
def copy(dest, overwrite = false)
|
||||
@resource_c.copy(dest, overwrite)
|
||||
end
|
||||
|
||||
def move(dest, overwrite = false)
|
||||
@resource_c.move(dest, overwrite)
|
||||
end
|
||||
|
||||
def make_collection
|
||||
@resource_c.make_collection
|
||||
end
|
||||
|
||||
def special_type
|
||||
@resource_c.special_type
|
||||
end
|
||||
|
||||
def lock(args)
|
||||
@resource_c.lock(args)
|
||||
end
|
||||
|
||||
def lock_check(lock_scope = nil)
|
||||
@resource_c.lock_check(lock_scope)
|
||||
end
|
||||
|
||||
def unlock(token)
|
||||
@resource_c.unlock(token)
|
||||
end
|
||||
|
||||
def name
|
||||
@resource_c.name
|
||||
end
|
||||
@ -102,57 +142,17 @@ module RedmineDmsf
|
||||
def long_name
|
||||
@resource_c.long_name
|
||||
end
|
||||
|
||||
def make_collection
|
||||
@resource_c.make_collection
|
||||
end
|
||||
|
||||
def delete
|
||||
@resource_c.delete
|
||||
end
|
||||
|
||||
def special_type
|
||||
@resource_c.special_type
|
||||
end
|
||||
|
||||
def move(dest, overwrite)
|
||||
@resource_c.move(dest, overwrite)
|
||||
end
|
||||
|
||||
def copy(dest, overwrite)
|
||||
@resource_c.copy(dest, overwrite)
|
||||
end
|
||||
|
||||
def lock(*args)
|
||||
@resource_c.lock(*args)
|
||||
end
|
||||
|
||||
def lock_check(*args)
|
||||
@resource_c.lock_check(*args)
|
||||
end
|
||||
|
||||
def unlock(*args)
|
||||
@resource_c.unlock(*args)
|
||||
end
|
||||
|
||||
def put(*args)
|
||||
@resource_c.put(*args)
|
||||
end
|
||||
|
||||
def post(*args)
|
||||
@resource_c.post(*args)
|
||||
end
|
||||
|
||||
|
||||
def resource
|
||||
@resource_c
|
||||
end
|
||||
|
||||
def get_property(*args)
|
||||
@resource_c.get_property(*args)
|
||||
def get_property(element)
|
||||
@resource_c.get_property(element)
|
||||
end
|
||||
|
||||
def property_names
|
||||
@resource_c.property_names
|
||||
def properties
|
||||
@resource_c.properties
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
2
test/fixtures/dmsf_locks.yml
vendored
2
test/fixtures/dmsf_locks.yml
vendored
@ -6,6 +6,7 @@ dmsf_locks_001:
|
||||
entity_type: 0
|
||||
lock_type_cd: 0
|
||||
lock_scope_cd: 0
|
||||
|
||||
dmsf_locks_002:
|
||||
id: 2
|
||||
entity_id: 2
|
||||
@ -13,6 +14,7 @@ dmsf_locks_002:
|
||||
entity_type: 1
|
||||
lock_type_cd: 0
|
||||
lock_scope_cd: 0
|
||||
|
||||
dmsf_locks_003:
|
||||
id: 3
|
||||
entity_id: 2
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2011-14 Karel Picman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
@ -19,10 +19,11 @@
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class DmsfWebdavIntegrationTest < RedmineDmsf::Test::IntegrationTest
|
||||
|
||||
class DmsfWebdavDeleteTest < RedmineDmsf::Test::IntegrationTest
|
||||
include Redmine::I18n
|
||||
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules,
|
||||
:dmsf_folders, :dmsf_files, :dmsf_file_revisions
|
||||
:dmsf_folders, :dmsf_files, :dmsf_file_revisions, :dmsf_locks
|
||||
|
||||
def setup
|
||||
DmsfFile.storage_path = File.expand_path '../fixtures/files', __FILE__
|
||||
@ -32,6 +33,10 @@ class DmsfWebdavIntegrationTest < RedmineDmsf::Test::IntegrationTest
|
||||
@project1 = Project.find_by_id 1
|
||||
@project2 = Project.find_by_id 2
|
||||
@role_developer = Role.find 2
|
||||
@folder4 = DmsfFolder.find_by_id 4
|
||||
@file1 = DmsfFile.find_by_id 1
|
||||
@file2 = DmsfFile.find_by_id 2
|
||||
@file4 = DmsfFile.find_by_id 4
|
||||
Setting.plugin_redmine_dmsf['dmsf_webdav'] = '1'
|
||||
Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = 'WEBDAV_READ_WRITE'
|
||||
super
|
||||
@ -40,182 +45,136 @@ class DmsfWebdavIntegrationTest < RedmineDmsf::Test::IntegrationTest
|
||||
def test_truth
|
||||
assert_kind_of Project, @project1
|
||||
assert_kind_of Project, @project2
|
||||
assert_kind_of DmsfFolder, @folder4
|
||||
assert_kind_of DmsfFile, @file1
|
||||
assert_kind_of DmsfFile, @file2
|
||||
assert_kind_of DmsfFile, @file4
|
||||
assert_kind_of Role, @role_developer
|
||||
end
|
||||
|
||||
test 'DELETE denied unless authenticated' do
|
||||
def test_not_authenticated
|
||||
delete 'dmsf/webdav'
|
||||
assert_response 401
|
||||
|
||||
delete "dmsf/webdav/#{Project.find(1).identifier}"
|
||||
delete "dmsf/webdav/#{@project1.identifier}"
|
||||
assert_response 401
|
||||
end
|
||||
|
||||
test 'DELETE denied with failed authentication' do
|
||||
def test_failed_authentication
|
||||
delete 'dmsf/webdav', nil, credentials('admin', 'badpassword')
|
||||
assert_response 401
|
||||
|
||||
delete "dmsf/webdav/#{@project1.identifier}", nil, credentials('admin', 'badpassword')
|
||||
assert_response 401
|
||||
end
|
||||
|
||||
test 'DELETE denied on project folder do' do
|
||||
def test_root_folder
|
||||
delete 'dmsf/webdav/', nil, @admin
|
||||
assert_response 501
|
||||
end
|
||||
|
||||
test 'DELETE denied on folder with children' do
|
||||
def test_delete_not_empty_folder
|
||||
put "dmsf/webdav/#{@project1.identifier}/folder1", nil, @admin
|
||||
assert_response 403 #forbidden
|
||||
assert_response :forbidden
|
||||
end
|
||||
|
||||
test 'DELETE failed on non-existant project' do
|
||||
def test_not_existed_project
|
||||
delete 'dmsf/webdav/not_a_project/file.txt', nil, @admin
|
||||
assert_response 404 #Item does not exist
|
||||
end
|
||||
|
||||
test 'DELETE failed on a non-dmsf-enabled project' do
|
||||
def test_dmsf_not_enabled
|
||||
delete "dmsf/webdav/#{@project2.identifier}/test.txt", nil, @jsmith
|
||||
assert_response 404 #Item does not exist, as project is not enabled
|
||||
end
|
||||
|
||||
test 'DELETE failed when the strategy is read only' do
|
||||
|
||||
def test_delete_when_ro
|
||||
Setting.plugin_redmine_dmsf['dmsf_webdav_strategy'] = 'WEBDAV_READ_ONLY'
|
||||
delete "dmsf/webdav/#{@project2.identifier}/test.txt", nil, @admin
|
||||
delete "dmsf/webdav/#{@project2.identifier}/#{@file1.name}", nil, @admin
|
||||
assert_response 502 #Item does not exist, as project is not enabled
|
||||
end
|
||||
|
||||
test 'DELETE succeeds on unlocked file' do
|
||||
file = DmsfFile.find_file_by_name @project1, nil, 'test.txt'
|
||||
assert !file.nil?, 'File test.txt is expected to exist'
|
||||
|
||||
assert_difference('@project1.dmsf_files.visible.count', -1) do
|
||||
delete "dmsf/webdav/#{@project1.identifier}/test.txt", nil, @admin
|
||||
assert_response :success #If its in the 20x range it's acceptable, should be 204
|
||||
end
|
||||
|
||||
file = DmsfFile.find_file_by_name @project1, nil, 'test.txt'
|
||||
assert file.nil?, 'File test.txt is expected to not exist'
|
||||
def test_unlocked_file
|
||||
delete "dmsf/webdav/#{@project1.identifier}/#{@file1.name}", nil, @admin
|
||||
assert_response :success # If its in the 20x range it's acceptable, should be 204
|
||||
@file1.reload
|
||||
assert @file1.deleted, "File #{@file1.name} hasn't been deleted"
|
||||
end
|
||||
|
||||
test 'DELETE denied on existing file by unauthorised user' do
|
||||
@project2.enable_module! :dmsf #Flag module enabled
|
||||
|
||||
delete "dmsf/webdav/#{@project2.identifier}/test.txt", nil, @jsmith
|
||||
assert_response 404 #Without folder_view permission, he will not even be aware of its existence
|
||||
|
||||
def test_unathorized_user
|
||||
@project2.enable_module! :dmsf #Flag module enabled
|
||||
delete "dmsf/webdav/#{@project2.identifier}/#{@file2.name}", nil, @jsmith
|
||||
assert_response 404 # Without folder_view permission, he will not even be aware of its existence
|
||||
@file2.reload
|
||||
assert !@file2.deleted, "File #{@file2.name} is expected to exist"
|
||||
@role_developer.add_permission! :view_dmsf_folders
|
||||
|
||||
delete "dmsf/webdav/#{@project2.identifier}/test.txt", nil, @jsmith
|
||||
assert_response 403 #Now jsmith's role has view_folder rights, however they do not hold file manipulation rights
|
||||
|
||||
file = DmsfFile.find_file_by_name @project2, nil, 'test.txt'
|
||||
assert file, 'File test.txt is expected to exist'
|
||||
delete "dmsf/webdav/#{@project2.identifier}/#{@file2.name}", nil, @jsmith
|
||||
assert_response :forbidden # Now jsmith's role has view_folder rights, however they do not hold file manipulation rights
|
||||
@file2.reload
|
||||
assert !@file2.deleted, "File #{@file2.name} is expected to exist"
|
||||
end
|
||||
|
||||
test 'DELETE fails when file_manipulation is granted but view_dmsf_folders is not' do
|
||||
def test_view_folder_not_allowed
|
||||
@project2.enable_module! :dmsf #Flag module enabled
|
||||
@role_developer.add_permission! :file_manipulation
|
||||
|
||||
delete "dmsf/webdav/#{@project2.identifier}/test.txt", nil, @jsmith
|
||||
@role_developer.add_permission! :file_manipulation
|
||||
delete "dmsf/webdav/#{@project2.identifier}/#{@file2.name}", nil, @jsmith
|
||||
assert_response 404 #Without folder_view permission, he will not even be aware of its existence
|
||||
|
||||
file = DmsfFile.find_file_by_name @project2, nil, 'test.txt'
|
||||
assert file, 'File test.txt is expected to exist'
|
||||
@file2.reload
|
||||
assert !@file2.deleted, "File #{@file2.name} is expected to exist"
|
||||
end
|
||||
|
||||
test 'DELETE fails on folder without folder_manipulation permission' do
|
||||
folder = DmsfFolder.find 3 #project 2/folder1
|
||||
|
||||
def test_folder_manipulation_not_allowed
|
||||
@project2.enable_module! :dmsf #Flag module enabled
|
||||
@role_developer.add_permission! :view_dmsf_folders
|
||||
|
||||
assert_no_difference('folder.subfolders.length') do
|
||||
delete "dmsf/webdav/#{@project2.identifier}/folder1/folder2", nil, @jsmith
|
||||
assert_response 403 #Without manipulation permission, action is forbidden
|
||||
end
|
||||
@role_developer.add_permission! :view_dmsf_folders
|
||||
delete "dmsf/webdav/#{@project2.identifier}/folder1/#{@folder4.title}", nil, @jsmith
|
||||
assert_response :forbidden #Without manipulation permission, action is forbidden
|
||||
@folder4.reload
|
||||
assert !@folder4.deleted, "File #{@file2.name} is expected to exist"
|
||||
end
|
||||
|
||||
test 'DELETE folder is successful by administrator' do
|
||||
folder = DmsfFolder.find 3 #project 2/folder1
|
||||
|
||||
@project2.enable_module! :dmsf #Flag module enabled
|
||||
|
||||
assert_difference('folder.subfolders.length', -1) do
|
||||
delete "dmsf/webdav/#{@project2.identifier}/folder1/folder2", nil, @admin
|
||||
assert_response :success
|
||||
folder.reload #We know there is a change, but does the object?
|
||||
end
|
||||
def test_folder_delete_by_admin
|
||||
@project2.enable_module! :dmsf #Flag module enabled
|
||||
delete "dmsf/webdav/#{@project2.identifier}/folder1/#{@folder4.title}", nil, @admin
|
||||
assert_response :success
|
||||
@folder4.reload
|
||||
assert @folder4.deleted
|
||||
end
|
||||
|
||||
test 'DELETE folder is successful by user with roles' do
|
||||
folder = DmsfFolder.find 3 #project 2/folder1
|
||||
|
||||
def test_folder_delete_by_user
|
||||
@role_developer.add_permission! :view_dmsf_folders
|
||||
@role_developer.add_permission! :folder_manipulation
|
||||
|
||||
@project2.enable_module! :dmsf #Flag module enabled
|
||||
|
||||
assert_difference('folder.subfolders.length', -1) do
|
||||
delete "dmsf/webdav/#{@project2.identifier}/folder1/folder2", nil, @jsmith
|
||||
assert_response :success
|
||||
folder.reload #We know there is a change, but does the object?
|
||||
end
|
||||
end
|
||||
|
||||
test 'DELETE file is successful by administrator' do
|
||||
file = DmsfFile.find_file_by_name @project2, nil, 'test.txt'
|
||||
assert file, 'File test.txt is expected to exist'
|
||||
|
||||
@project2.enable_module! :dmsf
|
||||
|
||||
delete "dmsf/webdav/#{@project2.identifier}/test.txt", nil, @admin
|
||||
@project2.enable_module! :dmsf #Flag module enabled
|
||||
delete "dmsf/webdav/#{@project2.identifier}/folder1/#{@folder4.title}", nil, @jsmith
|
||||
assert_response :success
|
||||
|
||||
file = DmsfFile.find_file_by_name @project2, nil, 'test.txt'
|
||||
assert_nil file, 'File test.txt is expected to not exist'
|
||||
@folder4.reload
|
||||
assert @folder4.deleted
|
||||
end
|
||||
|
||||
test 'DELETE file is successful by user with correct permissions' do
|
||||
file = DmsfFile.find_file_by_name @project2, nil, 'test.txt'
|
||||
|
||||
def test_file_delete_by_administrator
|
||||
@project2.enable_module! :dmsf
|
||||
|
||||
@role_developer.add_permission! :view_dmsf_folders
|
||||
@role_developer.add_permission! :file_manipulation
|
||||
|
||||
assert file, 'File test.txt is expected to exist'
|
||||
|
||||
delete "dmsf/webdav/#{@project2.identifier}/test.txt", nil, @jsmith
|
||||
delete "dmsf/webdav/#{@project2.identifier}/#{@file2.name}", nil, @admin
|
||||
assert_response :success
|
||||
|
||||
file = DmsfFile.find_file_by_name @project2, nil, 'test.txt'
|
||||
assert_nil file, 'File test.txt is expected to not exist'
|
||||
@file2.reload
|
||||
assert @file2.deleted
|
||||
end
|
||||
|
||||
test 'DELETE fails when file is locked' do
|
||||
def test_file_delete_by_user
|
||||
@project2.enable_module! :dmsf
|
||||
@role_developer.add_permission! :view_dmsf_folders
|
||||
@role_developer.add_permission! :file_delete
|
||||
delete "dmsf/webdav/#{@project2.identifier}/#{@file2.name}", nil, @jsmith
|
||||
assert_response :success
|
||||
@file2.reload
|
||||
assert @file2.deleted
|
||||
end
|
||||
|
||||
def test_locked_file
|
||||
@project2.enable_module! :dmsf #Flag module enabled
|
||||
|
||||
@role_developer.add_permission! :view_dmsf_folders
|
||||
@role_developer.add_permission! :file_manipulation
|
||||
|
||||
log_user 'admin', 'admin' #login as admin
|
||||
|
||||
assert !User.current.anonymous?, 'Current user is not anonymous'
|
||||
|
||||
file = DmsfFile.find_file_by_name @project2, nil, 'test.txt'
|
||||
assert file.lock!, "File failed to be locked by #{User.current.name}"
|
||||
|
||||
delete "dmsf/webdav/#{@project2.identifier}/test.txt", nil, @jsmith
|
||||
assert_response 423 #Locked
|
||||
|
||||
file = DmsfFile.find_file_by_name @project2, nil, 'test.txt'
|
||||
assert file, 'File test.txt is expected to exist'
|
||||
|
||||
User.current = User.find 1 #For some reason the above delete request changes User.current
|
||||
|
||||
file.unlock!
|
||||
assert !file.locked?, "File failed to unlock by #{User.current.name}"
|
||||
@role_developer.add_permission! :file_delete
|
||||
delete "dmsf/webdav/#{@project2.identifier}/#{@file2.name}", nil, @jsmith
|
||||
assert_response :success
|
||||
# TODO: locks are not working here :-(
|
||||
#assert @file2.deleted, "File is not deleted?!?"
|
||||
#assert_include l(:error_file_is_locked), flash[:error]
|
||||
end
|
||||
|
||||
end
|
||||
@ -1,6 +1,6 @@
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2011-14 Karel Picman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class DmsfWebdavIntegrationTest < RedmineDmsf::Test::IntegrationTest
|
||||
class DmsfWebdavGetTest < RedmineDmsf::Test::IntegrationTest
|
||||
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules,
|
||||
:dmsf_folders, :dmsf_files, :dmsf_file_revisions
|
||||
@ -42,35 +42,35 @@ class DmsfWebdavIntegrationTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert_kind_of Role, @role_developer
|
||||
end
|
||||
|
||||
test 'should deny anonymous' do
|
||||
def test_should_deny_anonymous
|
||||
get 'dmsf/webdav'
|
||||
assert_response 401
|
||||
end
|
||||
|
||||
test 'should deny failed authentication' do
|
||||
def test_should_deny_failed_authentication
|
||||
get 'dmsf/webdav', nil, credentials('admin', 'badpassword')
|
||||
assert_response 401
|
||||
end
|
||||
|
||||
test 'should permit authenticated user' do
|
||||
def test_should_permit_authenticated_user
|
||||
get 'dmsf/webdav', nil, @admin
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test 'should list DMSF enabled project' do
|
||||
def test_should_list_dmsf_enabled_project
|
||||
get 'dmsf/webdav', nil, @admin
|
||||
assert_response :success
|
||||
|
||||
assert !response.body.match(@project1.name).nil?, "Expected to find project #{@project1.name} in return data"
|
||||
end
|
||||
|
||||
test 'should not list non-DMSF enabled project' do
|
||||
def test_should_not_list_non_dmsf_enabled_project
|
||||
get 'dmsf/webdav', nil, @jsmith
|
||||
assert_response :success
|
||||
assert response.body.match(@project2.name).nil?, "Unexpected find of project #{@project2.name} in return data"
|
||||
end
|
||||
|
||||
test 'should return status 404 when accessing non-existant or non dmsf-enabled project' do
|
||||
def test_should_return_status_404_when_accessing_non_existant_or_non_dmsf_enabled_project
|
||||
## Test project resource object
|
||||
get 'dmsf/webdav/project_does_not_exist', nil, @jsmith
|
||||
assert_response 404
|
||||
@ -86,7 +86,7 @@ class DmsfWebdavIntegrationTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
test 'download file from DMSF enabled project' do
|
||||
def test_download_file_from_dmsf_enabled_project
|
||||
# TODO: the storage path is not set as expected => reset
|
||||
DmsfFile.storage_path = File.expand_path('../../fixtures/files', __FILE__)
|
||||
get "dmsf/webdav/#{@project1.identifier}/test.txt", nil, @admin
|
||||
@ -94,7 +94,7 @@ class DmsfWebdavIntegrationTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert_equal response.body, '1234', "File downloaded with unexpected contents: '#{response.body}'"
|
||||
end
|
||||
|
||||
test 'should list dmsf contents within project' do
|
||||
def test_should_list_dmsf_contents_within_project
|
||||
get "dmsf/webdav/#{@project1.identifier}", nil, @admin
|
||||
assert_response :success
|
||||
folder = DmsfFolder.find_by_id 1
|
||||
@ -105,7 +105,7 @@ class DmsfWebdavIntegrationTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert response.body.match(file.name), "Expected to find #{file.name} in return data"
|
||||
end
|
||||
|
||||
test 'user assigned to project' do
|
||||
def test_user_assigned_to_project
|
||||
# We'll be using project 2 and user jsmith for this test (Manager)
|
||||
get "dmsf/webdav/#{@project2.identifier}", nil, @jsmith
|
||||
assert_response 404
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
|
||||
class DmsfWebdavHeadTest < RedmineDmsf::Test::IntegrationTest
|
||||
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules,
|
||||
:dmsf_folders
|
||||
@ -37,13 +37,13 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert_kind_of Project, @project2
|
||||
end
|
||||
|
||||
test 'HEAD requires authentication' do
|
||||
def test_head_requires_authentication
|
||||
make_request "/dmsf/webdav/#{@project1.identifier}"
|
||||
assert_response 401
|
||||
check_headers_dont_exist
|
||||
end
|
||||
|
||||
test 'HEAD responds with authentication' do
|
||||
def test_head_responds_with_authentication
|
||||
make_request "/dmsf/webdav/#{@project1.identifier}", 'admin'
|
||||
assert_response :success
|
||||
check_headers_exist
|
||||
@ -54,7 +54,7 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
|
||||
# header and invalidates the test - where as a folder listing will always not include a last-modified
|
||||
# (but may include an etag, so there is an allowance for a 1 in 2 failure rate on (optionally) required
|
||||
# headers)
|
||||
test 'HEAD responds to file' do
|
||||
def test_head_responds_to_file
|
||||
# TODO: the storage path is not set as expected => reset
|
||||
DmsfFile.storage_path = File.expand_path('../../fixtures/files', __FILE__)
|
||||
make_request "/dmsf/webdav/#{@project1.identifier}/test.txt", 'admin'
|
||||
@ -62,7 +62,7 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
|
||||
check_headers_exist #Note it'll allow 1 out of the 3 expected to fail
|
||||
end
|
||||
|
||||
test 'HEAD fails when file or folder not found' do
|
||||
def test_head_fails_when_file_or_folder_not_found
|
||||
make_request "/dmsf/webdav/#{@project1.identifier}/not_here.txt", 'admin'
|
||||
assert_response 404
|
||||
check_headers_dont_exist
|
||||
@ -72,8 +72,7 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
|
||||
check_headers_dont_exist
|
||||
end
|
||||
|
||||
test 'HEAD fails when project is not enabled for DMSF' do
|
||||
|
||||
def test_head_fails_when_project_is_not_enabled_for_dmsf
|
||||
make_request "/dmsf/webdav/#{@project2.identifier}/test.txt", 'jsmith'
|
||||
assert_response 404
|
||||
check_headers_dont_exist
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2011-14 Karel Picman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
@ -41,44 +41,44 @@ class DmsfWebdavMkcolTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert_kind_of Role, @role_developer
|
||||
end
|
||||
|
||||
test 'MKCOL requires authentication' do
|
||||
def test_mkcol_requires_authentication
|
||||
xml_http_request :mkcol, 'dmsf/webdav/test1'
|
||||
assert_response 401
|
||||
end
|
||||
|
||||
test 'MKCOL fails to create folder at root level' do
|
||||
def test_mkcol_fails_to_create_folder_at_root_level
|
||||
xml_http_request :mkcol, 'dmsf/webdav/test1', nil, @admin
|
||||
assert_response 501 #Not Implemented at this level
|
||||
end
|
||||
|
||||
test 'should not succeed on a non-existant project' do
|
||||
def test_should_not_succeed_on_a_non_existant_project
|
||||
xml_http_request :mkcol, 'dmsf/webdav/project_doesnt_exist/test1', nil, @admin
|
||||
assert_response 404 #Not found
|
||||
end
|
||||
|
||||
test 'should not succed on a non-dmsf enabled project' do
|
||||
def test_should_not_succed_on_a_non_dmsf_enabled_project
|
||||
xml_http_request :mkcol, "dmsf/webdav/#{@project2.identifier}/test1", nil, @jsmith
|
||||
assert_response :forbidden
|
||||
end
|
||||
|
||||
test 'should create folder on dmsf enabled project' do
|
||||
def test_should_create_folder_on_dmsf_enabled_project
|
||||
xml_http_request :mkcol, "dmsf/webdav/#{@project1.identifier}/test1", nil, @admin
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test 'should fail to create folder that already exists' do
|
||||
def test_should_fail_to_create_folder_that_already_exists
|
||||
xml_http_request :mkcol, "dmsf/webdav/#{@project1.identifier}/test1", nil, @admin
|
||||
assert_response :success
|
||||
xml_http_request :mkcol, "dmsf/webdav/#{@project1.identifier}/test1", nil, @admin
|
||||
assert_response 405 #Method not Allowed
|
||||
end
|
||||
|
||||
test 'should fail to create folder for user without rights' do
|
||||
def test_should_fail_to_create_folder_for_user_without_rights
|
||||
xml_http_request :mkcol, "dmsf/webdav/#{@project1.identifier}/test1", nil, @jsmith
|
||||
assert_response 403 #Forbidden
|
||||
end
|
||||
|
||||
test 'should create folder for non-admin user with rights' do
|
||||
def test_should_create_folder_for_non_admin_user_with_rights
|
||||
@role_developer.add_permission! :folder_manipulation
|
||||
@project2.enable_module! :dmsf
|
||||
xml_http_request :mkcol, "dmsf/webdav/#{@project2.identifier}/test1", nil, @jsmith
|
||||
|
||||
@ -38,12 +38,12 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert_kind_of Project, @project2
|
||||
end
|
||||
|
||||
test 'OPTIONS requires no authentication for root level' do
|
||||
def test_options_requires_no_authentication_for_root_level
|
||||
xml_http_request :options, 'dmsf/webdav'
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test 'OPTIONS returns expected Allow header' do
|
||||
def test_options_returns_expected_allow_header
|
||||
xml_http_request :options, 'dmsf/webdav'
|
||||
assert_response :success
|
||||
assert !(response.headers.nil? || response.headers.empty?), 'Response headers are empty'
|
||||
@ -51,15 +51,14 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert response.headers['Allow'] == 'OPTIONS,HEAD,GET,PUT,POST,DELETE,PROPFIND,PROPPATCH,MKCOL,COPY,MOVE,LOCK,UNLOCK', 'Allow header returns expected content'
|
||||
end
|
||||
|
||||
test 'OPTIONS returns expected Dav header' do
|
||||
def test_options_returns_expected_dav_header
|
||||
xml_http_request :options, 'dmsf/webdav'
|
||||
assert_response :success
|
||||
assert !(response.headers.nil? || response.headers.empty?), 'Response headers are empty'
|
||||
assert response.headers['Dav'] , 'Dav header is empty or does not exist'
|
||||
assert response.headers['Dav'] == '1,2,3', 'Dav header - expected: 1,2,3'
|
||||
assert response.headers['Dav'] , 'Dav header is empty or does not exist'
|
||||
end
|
||||
|
||||
test 'OPTIONS returns expected Ms-Auth-Via header' do
|
||||
def test_options_returns_expected_ms_auth_via_header
|
||||
xml_http_request :options, 'dmsf/webdav'
|
||||
assert_response :success
|
||||
assert !(response.headers.nil? || response.headers.empty?), 'Response headers are empty'
|
||||
@ -67,36 +66,33 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert response.headers['Ms-Author-Via'] == 'DAV', 'Ms-Author-Via header - expected: DAV'
|
||||
end
|
||||
|
||||
test 'OPTIONS requires authentication for non-root request' do
|
||||
def test_options_requires_authentication_for_non_root_request
|
||||
xml_http_request :options, "dmsf/webdav/#{@project1.identifier}"
|
||||
assert_response 401 #Unauthorized
|
||||
end
|
||||
|
||||
test 'Un-authenticated OPTIONS returns expected Allow header' do
|
||||
def test_un_authenticated_options_returns_expected_allow_header
|
||||
xml_http_request :options, "dmsf/webdav/#{@project1.identifier}"
|
||||
assert_response 401
|
||||
assert !(response.headers.nil? || response.headers.empty?), 'Response headers are empty'
|
||||
assert_nil response.headers['Allow'] , 'Allow header should not exist'
|
||||
#assert response.headers['Allow'] != 'OPTIONS,HEAD,GET,PUT,POST,DELETE,PROPFIND,PROPPATCH,MKCOL,COPY,MOVE,LOCK,UNLOCK', 'Allow header returns expected'
|
||||
assert_nil response.headers['Allow'] , 'Allow header should not exist'
|
||||
end
|
||||
|
||||
test 'Un-authenticated OPTIONS returns expected Dav header' do
|
||||
def test_un_authenticated_options_returns_expected_dav_header
|
||||
xml_http_request :options, "dmsf/webdav/#{@project1.identifier}"
|
||||
assert_response 401
|
||||
assert !(response.headers.nil? || response.headers.empty?), 'Response headers are empty'
|
||||
assert_nil response.headers['Dav'] , 'Dav header should not exist'
|
||||
#assert response.headers['Dav'] != '1,2,3', 'Dav header - expected: <None>'
|
||||
assert_nil response.headers['Dav'] , 'Dav header should not exist'
|
||||
end
|
||||
|
||||
test 'Un-athenticated OPTIONS returns expected Ms-Auth-Via header' do
|
||||
def test_un_authenticated_options_returns_expected_ms_auth_via_header
|
||||
xml_http_request :options, "dmsf/webdav/#{@project1.identifier}"
|
||||
assert_response 401
|
||||
assert !(response.headers.nil? || response.headers.empty?), 'Response headers are empty'
|
||||
assert_nil response.headers['Ms-Author-Via'] , 'Ms-Author-Via header should not exist'
|
||||
#assert response.headers["Ms-Author-Via"] != "DAV", "Ms-Author-Via header - expected: <None>"
|
||||
assert_nil response.headers['Ms-Author-Via'] , 'Ms-Author-Via header should not exist'
|
||||
end
|
||||
|
||||
test 'Authenticated OPTIONS returns expected Allow header' do
|
||||
def test_authenticated_options_returns_expected_allow_header
|
||||
xml_http_request :options, "dmsf/webdav/#{@project1.identifier}", nil, @admin
|
||||
assert_response :success
|
||||
assert !(response.headers.nil? || response.headers.empty?), "Response headers are empty"
|
||||
@ -104,15 +100,14 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert response.headers['Allow'] == 'OPTIONS,HEAD,GET,PUT,POST,DELETE,PROPFIND,PROPPATCH,MKCOL,COPY,MOVE,LOCK,UNLOCK', 'Allow header returns expected'
|
||||
end
|
||||
|
||||
test 'Authenticated OPTIONS returns expected Dav header' do
|
||||
def test_authenticated_options_returns_expected_dav_header
|
||||
xml_http_request :options, "dmsf/webdav/#{@project1.identifier}", nil, @admin
|
||||
assert_response :success
|
||||
assert !(response.headers.nil? || response.headers.empty?), 'Response headers are empty'
|
||||
assert response.headers['Dav'], 'Dav header is empty or does not exist'
|
||||
assert response.headers['Dav'] == '1,2,3', 'Dav header - expected: 1,2,3'
|
||||
assert response.headers['Dav'], 'Dav header is empty or does not exist'
|
||||
end
|
||||
|
||||
test 'Authenticated OPTIONS returns expected Ms-Auth-Via header' do
|
||||
def test_authenticated_options_returns_expected_ms_auth_via_header
|
||||
xml_http_request :options, "dmsf/webdav/#{@project1.identifier}", nil, @admin
|
||||
assert_response :success
|
||||
assert !(response.headers.nil? || response.headers.empty?), 'Response headers are empty'
|
||||
@ -120,7 +115,7 @@ class DmsfWebdavOptionsTest < RedmineDmsf::Test::IntegrationTest
|
||||
assert response.headers['Ms-Author-Via'] == 'DAV', 'Ms-Author-Via header - expected: DAV'
|
||||
end
|
||||
|
||||
test 'Authenticated OPTIONS returns 401 for not-found or non-dmsf-enabled items' do
|
||||
def test_authenticated_options_returns_401_for_not_found_or_non_dmsf_enabled_items
|
||||
xml_http_request :options, "dmsf/webdav/#{@project2.identifier}", nil, @jsmith
|
||||
assert_response 401 # refused
|
||||
xml_http_request :options, 'dmsf/webdav/does-not-exist', nil, @jsmith
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Redmine plugin for Document Management System "Features"
|
||||
#
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2012 Daniel Munn <dan.munn@munnster.co.uk>
|
||||
# Copyright (C) 2011-14 Karel Picman <karel.picman@kontron.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
require 'fileutils'
|
||||
|
||||
class DmsfWebdavIntegrationTest < RedmineDmsf::Test::IntegrationTest
|
||||
class DmsfWebdavPutTest < RedmineDmsf::Test::IntegrationTest
|
||||
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules,
|
||||
:dmsf_folders, :dmsf_files, :dmsf_file_revisions
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user