Skip to content

Commit

Permalink
FE - Add file action to explicitly lock a file (but no folder)
Browse files Browse the repository at this point in the history
BE - Make sure href to the lockroot includes the base uri.
  • Loading branch information
DeepDiver1975 committed Jun 17, 2020
1 parent 1dad3e4 commit a75abb1
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 13 deletions.
15 changes: 15 additions & 0 deletions apps/dav/lib/Connector/Sabre/PublicDavLocksPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
namespace OCA\DAV\Connector\Sabre;

use Sabre\DAV\Locks\Backend\BackendInterface;
use Sabre\DAV\Locks\LockInfo;
use Sabre\DAV\PropFind;
use Sabre\DAV\INode;
use Sabre\DAV\Exception\MethodNotAllowed;
Expand Down Expand Up @@ -85,4 +86,18 @@ public function httpUnlock(RequestInterface $request, ResponseInterface $respons
throw new MethodNotAllowed('Locking not allowed from public endpoint');
}
}

/**
* Generates the response for successful LOCK requests.
* @todo this method can be removed once upstream released a new version with this fix https://github.com/sabre-io/dav/pull/1273
*
* @return string
*/
protected function generateLockResponse(LockInfo $lockInfo) {
$contextUri = $this->server->getBaseUri();

return $this->server->xml->write('{DAV:}prop', [
'{DAV:}lockdiscovery' => new LockDiscovery([$lockInfo]),
], $contextUri);
}
}
39 changes: 36 additions & 3 deletions apps/files/js/filelockplugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,9 @@
}).map(function(xmlvalue) {
return parseLockNode(xmlvalue);
}).value();

}
return data;
});


},

/**
Expand Down Expand Up @@ -154,6 +151,42 @@
}
});

if (oc_appconfig.files.enable_lock_file_action) {
fileList.fileActions.registerAction({
name: 'lock',
mime: 'all',
displayName: t('files', 'Lock file'),
permissions: OC.PERMISSION_UPDATE,
type: OCA.Files.FileActions.TYPE_DROPDOWN,
iconClass: 'icon-lock-open',
actionHandler: function (filename, context) {
const file = context.fileInfoModel.getFullPath();
context.fileInfoModel._filesClient.lock(file).then(function (result, response) {
const xml = response.xhr.responseXML;
const activelock = xml.getElementsByTagNameNS('DAV:', 'activelock');
const lock = parseLockNode(activelock[0]);
context.fileInfoModel.set('activeLocks', [lock]);
}, function (error) {
console.log(error)
OC.Notification.show(t('files', 'Failed to lock.'));
});
}
});

fileList.fileActions.addAdvancedFilter(function (actions, context) {
var $file = context.$file;
if (context.fileInfoModel && context.fileInfoModel.attributes.mimetype === 'httpd/unix-directory') {
delete (actions.lock);
return actions;
}
var isLocked = $file.data('activelocks');
if (isLocked && isLocked.length > 0) {
delete (actions.lock);
}
return actions;
});
}

},

renderLink: function () {
Expand Down
18 changes: 15 additions & 3 deletions apps/files/js/locktabview.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
var self = this;
var $target = $(event.target).closest('.lock-entry');
var lockIndex = parseInt($target.attr('data-index'), 10);

var currentLock = this.model.get('activeLocks')[lockIndex];

// FIXME: move to FileInfoModel
Expand All @@ -75,7 +74,6 @@
// implicit clone of array else backbone doesn't fire change event
var locks = _.without(self.model.get('activeLocks') || [], currentLock);
self.model.set('activeLocks', locks);
self.render();
}
else if (result.status === 403) {
OC.Notification.show(t('files', 'Could not unlock, please contact the lock owner {owner}', {owner: currentLock.owner}));
Expand Down Expand Up @@ -121,7 +119,21 @@
canDisplay: function(fileInfo) {
// don't display if no lock is set
return fileInfo && fileInfo.get('activeLocks') && fileInfo.get('activeLocks').length > 0;
}
},

setFileInfo: function(fileInfo) {
if (this.model !== fileInfo) {
this.model = fileInfo;
this.render();
if (fileInfo) {
const self = this;
this.model.on('change', function(data) {
self.render();
});
}
}
},

});

OCA.Files.LockTabView = LockTabView;
Expand Down
12 changes: 8 additions & 4 deletions apps/files/lib/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,17 @@ public static function getNavigationManager() {
}

public static function extendJsConfig($array) {
$maxChunkSize = (int)(\OC::$server->getConfig()->getAppValue('files', 'max_chunk_size', (10 * 1024 * 1024)));
$uploadStallTimeout = (int)(\OC::$server->getConfig()->getAppValue('files', 'upload_stall_timeout', 60)); // in seconds
$uploadStallRetries = (int)(\OC::$server->getConfig()->getAppValue('files', 'upload_stall_retries', 100));
$config = \OC::$server->getConfig();
$maxChunkSize = (int)($config->getAppValue('files', 'max_chunk_size', (10 * 1024 * 1024)));
$uploadStallTimeout = (int)($config->getAppValue('files', 'upload_stall_timeout', 60)); // in seconds
$uploadStallRetries = (int)($config->getAppValue('files', 'upload_stall_retries', 100));
$enableLockFileAction = (boolean)($config->getAppValue('files', 'enable_lock_file_action', false));

$array['array']['oc_appconfig']['files'] = [
'max_chunk_size' => $maxChunkSize,
'upload_stall_timeout' => $uploadStallTimeout,
'upload_stall_retries' => $uploadStallRetries
'upload_stall_retries' => $uploadStallRetries,
'enable_lock_file_action' => $enableLockFileAction
];
}
}
9 changes: 6 additions & 3 deletions apps/files/tests/js/filelockpluginSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ describe('OCA.Files.LockPlugin tests', function() {
var currentUserStub;

beforeEach(function() {
oc_appconfig = oc_appconfig || {};
oc_appconfig.files = oc_appconfig.files || {};
oc_appconfig.files.enable_lock_file_action = true;
var $content = $('<div id="content"></div>');
$('#testArea').append($content);
// dummy file list
Expand Down Expand Up @@ -134,8 +137,8 @@ describe('OCA.Files.LockPlugin tests', function() {
requestDeferred = new $.Deferred();
requestStub = sinon.stub(dav.Client.prototype, 'propFind').returns(requestDeferred.promise());
});
afterEach(function() {
requestStub.restore();
afterEach(function() {
requestStub.restore();
});

function makeLockXml(owner) {
Expand Down Expand Up @@ -186,7 +189,7 @@ describe('OCA.Files.LockPlugin tests', function() {

return xml;
}

it('parses lock information from response XML to JSON', function(done) {
var xml = dav.Client.prototype.parseMultiStatus(makeLockXml('lock owner'));
var promise = fileList.reload();
Expand Down
3 changes: 3 additions & 0 deletions changelog/unreleased/37460
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Change: Add file action to lock a file

https://github.com/owncloud/core/pull/37460
37 changes: 37 additions & 0 deletions core/js/files/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,43 @@
return promise;
},

lock: function(path, options) {
if (!path) {
throw 'Missing argument "path"';
}
var self = this;
var deferred = $.Deferred();
var promise = deferred.promise();

options = _.extend({
'pathIsUrl' : false
}, options);

const lockBody = "<?xml version='1.0' encoding='UTF-8'?>\n" +
"<d:lockinfo xmlns:d='DAV:'>\n" +
" <d:lockscope>\n" +
" <d:exclusive/>\n" +
" </d:lockscope>\n" +
"</d:lockinfo>\n";

this._client.request(
'LOCK',
options.pathIsUrl ? path : this._buildUrl(path),
{},
lockBody
).then(
function(result) {
if (self._isSuccessStatus(result.status)) {
deferred.resolve(result.status, result);
} else {
result = _.extend(result, self._getSabreException(result));
deferred.reject(result.status, result);
}
}
);
return promise;
},

/**
* Creates a directory
*
Expand Down

0 comments on commit a75abb1

Please sign in to comment.