Vim edit through webdav causes lose of all file versions besides last. #1413
This commit is contained in:
parent
8250b6d2cc
commit
7e62385ac3
@ -98,8 +98,12 @@ module RedmineDmsf
|
|||||||
# Return the content type of file
|
# Return the content type of file
|
||||||
# will return inode/directory for any collections, and appropriate for File entities
|
# will return inode/directory for any collections, and appropriate for File entities
|
||||||
def content_type
|
def content_type
|
||||||
if file&.last_revision
|
if file
|
||||||
file.last_revision.detect_content_type
|
if file.last_revision
|
||||||
|
file.last_revision.detect_content_type
|
||||||
|
else
|
||||||
|
'application/octet-stream'
|
||||||
|
end
|
||||||
else
|
else
|
||||||
'inode/directory'
|
'inode/directory'
|
||||||
end
|
end
|
||||||
@ -118,8 +122,12 @@ module RedmineDmsf
|
|||||||
def last_modified
|
def last_modified
|
||||||
if folder
|
if folder
|
||||||
folder.updated_at
|
folder.updated_at
|
||||||
elsif file&.last_revision
|
elsif file
|
||||||
file.last_revision.updated_at
|
if file.last_revision
|
||||||
|
file.last_revision.updated_at
|
||||||
|
else
|
||||||
|
file.updated_at
|
||||||
|
end
|
||||||
else
|
else
|
||||||
raise NotFound
|
raise NotFound
|
||||||
end
|
end
|
||||||
@ -186,6 +194,7 @@ module RedmineDmsf
|
|||||||
# <instance> should be of entity to be deleted, we simply follow the Dmsf entity method
|
# <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.
|
# for deletion and return of appropriate status based on outcome.
|
||||||
def delete
|
def delete
|
||||||
|
Rails.logger.info ">>> DELETE #{@path}"
|
||||||
if file
|
if file
|
||||||
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_delete, project)
|
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_delete, project)
|
||||||
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder, false))
|
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder, false))
|
||||||
@ -194,7 +203,7 @@ module RedmineDmsf
|
|||||||
if pattern.present? && basename.match(pattern)
|
if pattern.present? && basename.match(pattern)
|
||||||
# Files that are not versioned should be destroyed
|
# Files that are not versioned should be destroyed
|
||||||
destroy = true
|
destroy = true
|
||||||
elsif file.last_revision.size == 0
|
elsif (!file.last_revision) || file.last_revision.size == 0
|
||||||
# Zero-sized files should be destroyed
|
# Zero-sized files should be destroyed
|
||||||
destroy = true
|
destroy = true
|
||||||
else
|
else
|
||||||
@ -222,6 +231,13 @@ module RedmineDmsf
|
|||||||
# Process incoming MOVE request
|
# Process incoming MOVE request
|
||||||
# Behavioural differences between collection and single entity
|
# Behavioural differences between collection and single entity
|
||||||
def move(dest_path, overwrite)
|
def move(dest_path, overwrite)
|
||||||
|
# Don't allow editors like vi to create a temporary file during saving as they deletes it later including the
|
||||||
|
# document's history and saves a completely new document
|
||||||
|
Rails.logger.info ">>> MOVE #{@path} to #{dest_path}"
|
||||||
|
# if("#{@path}~" == dest_path)
|
||||||
|
# Rails.logger.info ">>> MethodNotAllowed"
|
||||||
|
# return MethodNotAllowed
|
||||||
|
# end
|
||||||
dest = ResourceProxy.new(dest_path, @request, @response, @options.merge(user: @user))
|
dest = ResourceProxy.new(dest_path, @request, @response, @options.merge(user: @user))
|
||||||
return PreconditionFailed if !dest.resource.is_a?(DmsfResource) || dest.resource.project.nil?
|
return PreconditionFailed if !dest.resource.is_a?(DmsfResource) || dest.resource.project.nil?
|
||||||
parent = dest.resource.parent
|
parent = dest.resource.parent
|
||||||
@ -420,13 +436,27 @@ module RedmineDmsf
|
|||||||
|
|
||||||
# Lock
|
# Lock
|
||||||
def lock(args)
|
def lock(args)
|
||||||
|
Rails.logger.info ">>> LOCK #{@path}"
|
||||||
unless parent&.exist?
|
unless parent&.exist?
|
||||||
e = Dav4rack::LockFailure.new
|
e = Dav4rack::LockFailure.new
|
||||||
e.add_failure @path, Conflict
|
e.add_failure @path, Conflict
|
||||||
raise e
|
raise e
|
||||||
end
|
end
|
||||||
unless exist?
|
unless exist?
|
||||||
return super(args)
|
# A successful lock request to an unmapped URL MUST result in the creation of a locked (non-collection)
|
||||||
|
# resource with empty content.
|
||||||
|
f = create_empty_file
|
||||||
|
if f
|
||||||
|
scope = "scope_#{(args[:scope] || 'exclusive')}".to_sym
|
||||||
|
type = "type_#{(args[:type] || 'write')}".to_sym
|
||||||
|
l = f.lock!(scope, type, Time.current + 1.weeks, args[:owner])
|
||||||
|
@response['Lock-Token'] = l.uuid
|
||||||
|
return [1.week.to_i, l.uuid]
|
||||||
|
else
|
||||||
|
e = Dav4rack::LockFailure.new
|
||||||
|
e.add_failure @path, NotFound
|
||||||
|
raise e
|
||||||
|
end
|
||||||
end
|
end
|
||||||
lock_check args
|
lock_check args
|
||||||
entity = file || folder
|
entity = file || folder
|
||||||
@ -479,6 +509,7 @@ module RedmineDmsf
|
|||||||
# Token based unlock (authenticated) will ensure that a correct token is sent, further ensuring
|
# Token based unlock (authenticated) will ensure that a correct token is sent, further ensuring
|
||||||
# ownership of token before permitting unlock
|
# ownership of token before permitting unlock
|
||||||
def unlock(token)
|
def unlock(token)
|
||||||
|
Rails.logger.info ">>> UNLOCK #{@path}"
|
||||||
unless exist?
|
unless exist?
|
||||||
return super(token)
|
return super(token)
|
||||||
end
|
end
|
||||||
@ -516,6 +547,7 @@ module RedmineDmsf
|
|||||||
|
|
||||||
# HTTP PUT request.
|
# HTTP PUT request.
|
||||||
def put(request, response)
|
def put(request, response)
|
||||||
|
Rails.logger.info ">>> PUT #{@path}"
|
||||||
raise BadRequest if collection?
|
raise BadRequest if collection?
|
||||||
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_manipulation, project)
|
raise Forbidden unless User.current.admin? || User.current.allowed_to?(:file_manipulation, project)
|
||||||
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder, false))
|
raise Forbidden unless (!parent.exist? || !parent.folder || DmsfFolder.permissions?(parent.folder, false))
|
||||||
@ -735,6 +767,33 @@ module RedmineDmsf
|
|||||||
return "Project-#{project.id}"
|
return "Project-#{project.id}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def create_empty_file
|
||||||
|
f = DmsfFile.new
|
||||||
|
f.project_id = project.id
|
||||||
|
f.name = basename
|
||||||
|
f.dmsf_folder = parent.folder
|
||||||
|
if f.save(validate: false) # Skip validation due to invalid characters in the filename
|
||||||
|
r = DmsfFileRevision.new
|
||||||
|
r.minor_version = 1
|
||||||
|
r.major_version = 0
|
||||||
|
r.title = DmsfFileRevision.filename_to_title(basename)
|
||||||
|
r.dmsf_file = f
|
||||||
|
r.user = User.current
|
||||||
|
r.name = basename
|
||||||
|
r.mime_type = Redmine::MimeType.of(r.name)
|
||||||
|
r.size = 0
|
||||||
|
r.digest = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|
||||||
|
r.disk_filename = r.new_storage_filename
|
||||||
|
if r.save(validate: false) # Skip validation due to invalid characters in the filename
|
||||||
|
FileUtils.touch r.disk_file(false)
|
||||||
|
return f
|
||||||
|
end
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user