summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/dav/lib/CalDAV/Schedule/IMipPlugin.php2
-rw-r--r--apps/dav/lib/CardDAV/AddressBookImpl.php35
-rw-r--r--apps/dav/lib/CardDAV/CardDavBackend.php4
-rw-r--r--apps/dav/lib/Connector/Sabre/File.php27
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FileTest.php6
-rw-r--r--apps/files/css/detailsView.scss10
-rw-r--r--apps/files/css/files.scss16
-rw-r--r--apps/files/js/detailsview.js3
-rw-r--r--apps/files/js/detailtabview.js15
-rw-r--r--apps/files/l10n/cs.js1
-rw-r--r--apps/files/l10n/cs.json1
-rw-r--r--apps/files_external/js/app.js28
-rw-r--r--apps/files_external/js/mountsfilelist.js10
-rw-r--r--apps/files_external/js/oauth1.js6
-rw-r--r--apps/files_external/js/oauth2.js6
-rw-r--r--apps/files_external/js/public_key.js4
-rw-r--r--apps/files_external/js/rollingqueue.js10
-rw-r--r--apps/files_external/js/settings.js54
-rw-r--r--apps/files_external/js/statusmanager.js56
-rw-r--r--apps/files_external/js/templates.js2
-rw-r--r--apps/files_external/tests/appSpec.js4
-rw-r--r--apps/files_external/tests/js/mountsfilelistSpec.js4
-rw-r--r--apps/files_external/tests/js/settingsSpec.js4
-rw-r--r--apps/files_sharing/css/sharetabview.scss29
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php14
-rw-r--r--apps/files_sharing/lib/Controller/ShareController.php15
-rw-r--r--apps/files_sharing/templates/public.php9
-rw-r--r--apps/files_sharing/tests/Controller/ShareAPIControllerTest.php21
-rw-r--r--apps/files_sharing/tests/Controller/ShareControllerTest.php117
-rw-r--r--apps/files_versions/appinfo/info.xml4
-rw-r--r--apps/files_versions/composer/composer/autoload_classmap.php7
-rw-r--r--apps/files_versions/composer/composer/autoload_static.php7
-rw-r--r--apps/files_versions/js/versionstabview.js4
-rw-r--r--apps/files_versions/lib/AppInfo/Application.php48
-rw-r--r--apps/files_versions/lib/Controller/PreviewController.php47
-rw-r--r--apps/files_versions/lib/Sabre/RestoreFolder.php12
-rw-r--r--apps/files_versions/lib/Sabre/RootCollection.php25
-rw-r--r--apps/files_versions/lib/Sabre/VersionCollection.php22
-rw-r--r--apps/files_versions/lib/Sabre/VersionFile.php41
-rw-r--r--apps/files_versions/lib/Sabre/VersionHome.php37
-rw-r--r--apps/files_versions/lib/Sabre/VersionRoot.php18
-rw-r--r--apps/files_versions/lib/Storage.php25
-rw-r--r--apps/files_versions/lib/Versions/BackendNotFoundException.php26
-rw-r--r--apps/files_versions/lib/Versions/IVersion.php99
-rw-r--r--apps/files_versions/lib/Versions/IVersionBackend.php81
-rw-r--r--apps/files_versions/lib/Versions/IVersionManager.php36
-rw-r--r--apps/files_versions/lib/Versions/LegacyVersionsBackend.php105
-rw-r--r--apps/files_versions/lib/Versions/Version.php113
-rw-r--r--apps/files_versions/lib/Versions/VersionManager.php93
-rw-r--r--apps/files_versions/tests/Controller/PreviewControllerTest.php55
-rw-r--r--apps/oauth2/lib/Controller/OauthApiController.php12
-rw-r--r--apps/oauth2/tests/Controller/OauthApiControllerTest.php44
-rw-r--r--apps/sharebymail/tests/CapabilitiesTest.php51
-rw-r--r--apps/systemtags/tests/Activity/SettingTest.php72
-rw-r--r--apps/user_ldap/composer/composer/autoload_classmap.php1
-rw-r--r--apps/user_ldap/composer/composer/autoload_static.php1
-rw-r--r--apps/user_ldap/lib/Access.php3
-rw-r--r--apps/user_ldap/lib/User/IUserTools.php42
-rw-r--r--apps/user_ldap/lib/User/Manager.php10
-rw-r--r--apps/user_ldap/lib/User/User.php21
-rw-r--r--apps/user_ldap/tests/User/ManagerTest.php224
-rw-r--r--apps/user_ldap/tests/User/UserTest.php43
62 files changed, 1494 insertions, 448 deletions
diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
index 6f303acba33..3ff3ed0c569 100644
--- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
+++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
@@ -170,7 +170,7 @@ class IMipPlugin extends SabreIMipPlugin {
$vevent = $iTipMessage->message->VEVENT;
$attendee = $this->getCurrentAttendee($iTipMessage);
- $defaultLang = $this->config->getUserValue($this->userId, 'core', 'lang', $this->l10nFactory->findLanguage());
+ $defaultLang = $this->l10nFactory->findLanguage();
$lang = $this->getAttendeeLangOrDefault($defaultLang, $attendee);
$l10n = $this->l10nFactory->get('dav', $lang);
diff --git a/apps/dav/lib/CardDAV/AddressBookImpl.php b/apps/dav/lib/CardDAV/AddressBookImpl.php
index 5034b16ed2f..1aedd5d5643 100644
--- a/apps/dav/lib/CardDAV/AddressBookImpl.php
+++ b/apps/dav/lib/CardDAV/AddressBookImpl.php
@@ -88,16 +88,26 @@ class AddressBookImpl implements IAddressBook {
/**
* @param string $pattern which should match within the $searchProperties
* @param array $searchProperties defines the properties within the query pattern should match
- * @param array $options - for future use. One should always have options!
+ * @param array $options Options to define the output format
+ * - types boolean (since 15.0.0) If set to true, fields that come with a TYPE property will be an array
+ * example: ['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['type => 'HOME', 'value' => 'g@h.i']]
+ * @return array an array of contacts which are arrays of key-value-pairs
+ * example result:
+ * [
+ * ['id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', 'GEO' => '37.386013;-122.082932'],
+ * ['id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => ['d@e.f', 'g@h.i']]
+ * ]
* @return array an array of contacts which are arrays of key-value-pairs
* @since 5.0.0
*/
public function search($pattern, $searchProperties, $options) {
$results = $this->backend->search($this->getKey(), $pattern, $searchProperties);
+ $withTypes = \array_key_exists('types', $options) && $options['types'] === true;
+
$vCards = [];
foreach ($results as $result) {
- $vCards[] = $this->vCard2Array($result['uri'], $this->readCard($result['carddata']));
+ $vCards[] = $this->vCard2Array($result['uri'], $this->readCard($result['carddata']), $withTypes);
}
return $vCards;
@@ -220,7 +230,7 @@ class AddressBookImpl implements IAddressBook {
* @param VCard $vCard
* @return array
*/
- protected function vCard2Array($uri, VCard $vCard) {
+ protected function vCard2Array($uri, VCard $vCard, $withTypes = false) {
$result = [
'URI' => $uri,
];
@@ -255,15 +265,28 @@ class AddressBookImpl implements IAddressBook {
$result[$property->name] = [];
}
- $result[$property->name][] = $property->getValue();
+ $type = $this->getTypeFromProperty($property);
+ if ($withTypes) {
+ $result[$property->name][] = [
+ 'type' => $type,
+ 'value' => $property->getValue()
+ ];
+ } else {
+ $result[$property->name][] = $property->getValue();
+ }
+
} else {
$result[$property->name] = $property->getValue();
}
}
- if ($this->addressBookInfo['principaluri'] === 'principals/system/system' &&
- $this->addressBookInfo['uri'] === 'system') {
+ if (
+ $this->addressBookInfo['principaluri'] === 'principals/system/system' && (
+ $this->addressBookInfo['uri'] === 'system' ||
+ $this->addressBookInfo['{DAV:}displayname'] === $this->urlGenerator->getBaseUrl()
+ )
+ ) {
$result['isLocalSystemBook'] = true;
}
return $result;
diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php
index 8ef0e0baf56..80a3fe2f11f 100644
--- a/apps/dav/lib/CardDAV/CardDavBackend.php
+++ b/apps/dav/lib/CardDAV/CardDavBackend.php
@@ -1134,8 +1134,8 @@ class CardDavBackend implements BackendInterface, SyncSupport {
* Extract UID from vcard
*
* @param string $cardData the vcard raw data
- * @return string the uid or empty if none
- * @throws BadRequest
+ * @return string the uid
+ * @throws BadRequest if no UID is available
*/
private function getUID($cardData) {
$vCard = Reader::read($cardData);
diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php
index 9e927ff85e5..57c072fda47 100644
--- a/apps/dav/lib/Connector/Sabre/File.php
+++ b/apps/dav/lib/Connector/Sabre/File.php
@@ -164,14 +164,19 @@ class File extends Node implements IFile {
$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
}
- $target = $partStorage->fopen($internalPartPath, 'wb');
- if ($target === false) {
- \OC::$server->getLogger()->error('\OC\Files\Filesystem::fopen() failed', ['app' => 'webdav']);
- // because we have no clue about the cause we can only throw back a 500/Internal Server Error
- throw new Exception('Could not write file contents');
+ if ($partStorage->instanceOfStorage(Storage\IWriteStreamStorage::class)) {
+ $count = $partStorage->writeStream($internalPartPath, $data);
+ $result = $count > 0;
+ } else {
+ $target = $partStorage->fopen($internalPartPath, 'wb');
+ if ($target === false) {
+ \OC::$server->getLogger()->error('\OC\Files\Filesystem::fopen() failed', ['app' => 'webdav']);
+ // because we have no clue about the cause we can only throw back a 500/Internal Server Error
+ throw new Exception('Could not write file contents');
+ }
+ list($count, $result) = \OC_Helper::streamCopy($data, $target);
+ fclose($target);
}
- list($count, $result) = \OC_Helper::streamCopy($data, $target);
- fclose($target);
if ($result === false) {
$expected = -1;
@@ -185,7 +190,7 @@ class File extends Node implements IFile {
// double check if the file was fully received
// compare expected and actual size
if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
- $expected = (int) $_SERVER['CONTENT_LENGTH'];
+ $expected = (int)$_SERVER['CONTENT_LENGTH'];
if ($count !== $expected) {
throw new BadRequest('expected filesize ' . $expected . ' got ' . $count);
}
@@ -219,7 +224,7 @@ class File extends Node implements IFile {
$renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
$fileExists = $storage->file_exists($internalPath);
if ($renameOkay === false || $fileExists === false) {
- \OC::$server->getLogger()->error('renaming part file to final file failed ($run: ' . ( $run ? 'true' : 'false' ) . ', $renameOkay: ' . ( $renameOkay ? 'true' : 'false' ) . ', $fileExists: ' . ( $fileExists ? 'true' : 'false' ) . ')', ['app' => 'webdav']);
+ \OC::$server->getLogger()->error('renaming part file to final file failed $renameOkay: ' . ($renameOkay ? 'true' : 'false') . ', $fileExists: ' . ($fileExists ? 'true' : 'false') . ')', ['app' => 'webdav']);
throw new Exception('Could not rename part file to final file');
}
} catch (ForbiddenException $ex) {
@@ -246,7 +251,7 @@ class File extends Node implements IFile {
$this->header('X-OC-MTime: accepted');
}
}
-
+
if ($view) {
$this->emitPostHooks($exists);
}
@@ -443,7 +448,7 @@ class File extends Node implements IFile {
//detect aborted upload
if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
if (isset($_SERVER['CONTENT_LENGTH'])) {
- $expected = (int) $_SERVER['CONTENT_LENGTH'];
+ $expected = (int)$_SERVER['CONTENT_LENGTH'];
if ($bytesWritten !== $expected) {
$chunk_handler->remove($info['index']);
throw new BadRequest(
diff --git a/apps/dav/tests/unit/Connector/Sabre/FileTest.php b/apps/dav/tests/unit/Connector/Sabre/FileTest.php
index 5e7a6374206..edb61edc6ed 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FileTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FileTest.php
@@ -164,7 +164,7 @@ class FileTest extends \Test\TestCase {
public function testSimplePutFails($thrownException, $expectedException, $checkPreviousClass = true) {
// setup
$storage = $this->getMockBuilder(Local::class)
- ->setMethods(['fopen'])
+ ->setMethods(['writeStream'])
->setConstructorArgs([['datadir' => \OC::$server->getTempManager()->getTemporaryFolder()]])
->getMock();
\OC\Files\Filesystem::mount($storage, [], $this->user . '/');
@@ -182,11 +182,11 @@ class FileTest extends \Test\TestCase {
if ($thrownException !== null) {
$storage->expects($this->once())
- ->method('fopen')
+ ->method('writeStream')
->will($this->throwException($thrownException));
} else {
$storage->expects($this->once())
- ->method('fopen')
+ ->method('writeStream')
->will($this->returnValue(false));
}
diff --git a/apps/files/css/detailsView.scss b/apps/files/css/detailsView.scss
index f64a3702850..71062648c97 100644
--- a/apps/files/css/detailsView.scss
+++ b/apps/files/css/detailsView.scss
@@ -15,7 +15,13 @@
#app-sidebar .mainFileInfoView .permalink {
padding: 6px 10px;
- vertical-align: text-top;
+ vertical-align: top;
+ opacity: .6;
+
+ &:hover,
+ &:focus {
+ opacity: 1;
+ }
}
#app-sidebar .mainFileInfoView .permalink-field>input {
clear: both;
@@ -87,7 +93,7 @@
}
#app-sidebar .fileName h3 {
- width: calc(100% - 36px); /* 36px is the with of the copy link icon */
+ width: calc(100% - 42px); /* 36px is the with of the copy link icon, but this breaks so we add some more to be sure */
display: inline-block;
padding: 5px 0;
margin: -5px 0;
diff --git a/apps/files/css/files.scss b/apps/files/css/files.scss
index 4e0bc9c0160..d6f9bd6131e 100644
--- a/apps/files/css/files.scss
+++ b/apps/files/css/files.scss
@@ -8,7 +8,12 @@
}
/* FILE MENU */
-.actions { padding:5px; height:32px; display: inline-block; float: left; }
+.actions {
+ padding: 5px;
+ height: 100%;
+ display: inline-block;
+ float: left;
+}
.actions input, .actions button, .actions .button { margin:0; float:left; }
.actions .button a { color: #555; }
.actions .button a:hover,
@@ -316,6 +321,7 @@ table td.filename .thumbnail {
background-size: 32px;
margin-left: 9px;
margin-top: 9px;
+ border-radius: var(--border-radius);
cursor: pointer;
position: absolute;
z-index: 4;
@@ -658,8 +664,14 @@ table.dragshadow td.size {
top: 100%;
margin-top: 4px;
min-width: 100px;
- margin-left: 7px;
+ margin-left: 22px; /* Align left edge below center of + button … */
+ transform: translateX(-50%); /* … then center it below button */
z-index: 1001;
+
+ /* Center triangle */
+ &::after {
+ left: calc(50% - 8px) !important;
+ }
}
#filestable .filename .action .icon,
diff --git a/apps/files/js/detailsview.js b/apps/files/js/detailsview.js
index cd602961c0a..bac2a5ebd21 100644
--- a/apps/files/js/detailsview.js
+++ b/apps/files/js/detailsview.js
@@ -174,6 +174,9 @@
// hide other tabs
$tabsContainer.find('.tab').addClass('hidden');
+ $tabsContainer.attr('class', 'tabsContainer');
+ $tabsContainer.addClass(tabView.getTabsContainerExtraClasses());
+
// tab already rendered ?
if (!$tabEl.length) {
// render tab
diff --git a/apps/files/js/detailtabview.js b/apps/files/js/detailtabview.js
index a66cedbc15d..1e046f30246 100644
--- a/apps/files/js/detailtabview.js
+++ b/apps/files/js/detailtabview.js
@@ -41,6 +41,21 @@
},
/**
+ * Returns the extra CSS classes used by the tabs container when this
+ * tab is the selected one.
+ *
+ * In general you should not extend this method, as tabs should not
+ * modify the classes of its container; this is reserved as a last
+ * resort for very specific cases in which there is no other way to get
+ * the proper style or behaviour.
+ *
+ * @return {String} space-separated CSS classes
+ */
+ getTabsContainerExtraClasses: function() {
+ return '';
+ },
+
+ /**
* Returns the tab label
*
* @return {String} label
diff --git a/apps/files/l10n/cs.js b/apps/files/l10n/cs.js
index cbd6c72d572..96b93d361e7 100644
--- a/apps/files/l10n/cs.js
+++ b/apps/files/l10n/cs.js
@@ -142,6 +142,7 @@ OC.L10N.register(
"WebDAV" : "WebDAV",
"Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">access your Files via WebDAV</a>" : "Použijte tuto adresu pro <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">přístup k vašim souborům přes WebDAV</a>",
"Cancel upload" : "Zrušit nahrávání",
+ "Toggle grid view" : "Přepnout zobrazení mřížky",
"No files in here" : "Žádné soubory",
"Upload some content or sync with your devices!" : "Nahrajte nějaký obsah nebo synchronizujte se svými přístroji!",
"No entries found in this folder" : "V této složce nebylo nic nalezeno",
diff --git a/apps/files/l10n/cs.json b/apps/files/l10n/cs.json
index a8f82c5c5d7..cb01165503d 100644
--- a/apps/files/l10n/cs.json
+++ b/apps/files/l10n/cs.json
@@ -140,6 +140,7 @@
"WebDAV" : "WebDAV",
"Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">access your Files via WebDAV</a>" : "Použijte tuto adresu pro <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">přístup k vašim souborům přes WebDAV</a>",
"Cancel upload" : "Zrušit nahrávání",
+ "Toggle grid view" : "Přepnout zobrazení mřížky",
"No files in here" : "Žádné soubory",
"Upload some content or sync with your devices!" : "Nahrajte nějaký obsah nebo synchronizujte se svými přístroji!",
"No entries found in this folder" : "V této složce nebylo nic nalezeno",
diff --git a/apps/files_external/js/app.js b/apps/files_external/js/app.js
index d3f738dcf8a..4406882cd21 100644
--- a/apps/files_external/js/app.js
+++ b/apps/files_external/js/app.js
@@ -8,16 +8,16 @@
*
*/
-if (!OCA.External) {
+if (!OCA.Files_External) {
/**
* @namespace
*/
- OCA.External = {};
+ OCA.Files_External = {};
}
/**
* @namespace
*/
-OCA.External.App = {
+OCA.Files_External.App = {
fileList: null,
@@ -26,7 +26,7 @@ OCA.External.App = {
return this.fileList;
}
- this.fileList = new OCA.External.FileList(
+ this.fileList = new OCA.Files_External.FileList(
$el,
{
fileActions: this._createFileActions()
@@ -67,10 +67,10 @@ OCA.External.App = {
$(document).ready(function() {
$('#app-content-extstoragemounts').on('show', function(e) {
- OCA.External.App.initList($(e.target));
+ OCA.Files_External.App.initList($(e.target));
});
$('#app-content-extstoragemounts').on('hide', function() {
- OCA.External.App.removeList();
+ OCA.Files_External.App.removeList();
});
/* Status Manager */
@@ -82,27 +82,27 @@ $(document).ready(function() {
if (e.dir === '/') {
var mount_point = e.previousDir.split('/', 2)[1];
// Every time that we return to / root folder from a mountpoint, mount_point status is rechecked
- OCA.External.StatusManager.getMountPointList(function() {
- OCA.External.StatusManager.recheckConnectivityForMount([mount_point], true);
+ OCA.Files_External.StatusManager.getMountPointList(function() {
+ OCA.Files_External.StatusManager.recheckConnectivityForMount([mount_point], true);
});
}
})
.on('fileActionsReady', function(e){
if ($.isArray(e.$files)) {
- if (OCA.External.StatusManager.mountStatus === null ||
- OCA.External.StatusManager.mountPointList === null ||
- _.size(OCA.External.StatusManager.mountStatus) !== _.size(OCA.External.StatusManager.mountPointList)) {
+ if (OCA.Files_External.StatusManager.mountStatus === null ||
+ OCA.Files_External.StatusManager.mountPointList === null ||
+ _.size(OCA.Files_External.StatusManager.mountStatus) !== _.size(OCA.Files_External.StatusManager.mountPointList)) {
// Will be the very first check when the files view will be loaded
- OCA.External.StatusManager.launchFullConnectivityCheckOneByOne();
+ OCA.Files_External.StatusManager.launchFullConnectivityCheckOneByOne();
} else {
// When we change between general files view and external files view
- OCA.External.StatusManager.getMountPointList(function(){
+ OCA.Files_External.StatusManager.getMountPointList(function(){
var fileNames = [];
$.each(e.$files, function(key, value){
fileNames.push(value.attr('data-file'));
});
// Recheck if launched but work from cache
- OCA.External.StatusManager.recheckConnectivityForMount(fileNames, false);
+ OCA.Files_External.StatusManager.recheckConnectivityForMount(fileNames, false);
});
}
}
diff --git a/apps/files_external/js/mountsfilelist.js b/apps/files_external/js/mountsfilelist.js
index 90b90e38745..034c29c05c2 100644
--- a/apps/files_external/js/mountsfilelist.js
+++ b/apps/files_external/js/mountsfilelist.js
@@ -10,7 +10,7 @@
(function() {
/**
- * @class OCA.External.FileList
+ * @class OCA.Files_External.FileList
* @augments OCA.Files.FileList
*
* @classdesc External storage file list.
@@ -27,7 +27,7 @@
};
FileList.prototype = _.extend({}, OCA.Files.FileList.prototype,
- /** @lends OCA.External.FileList.prototype */ {
+ /** @lends OCA.Files_External.FileList.prototype */ {
appName: 'External storages',
_allowSelection: false,
@@ -43,7 +43,7 @@
},
/**
- * @param {OCA.External.MountPointInfo} fileData
+ * @param {OCA.Files_External.MountPointInfo} fileData
*/
_createRow: function(fileData) {
// TODO: hook earlier and render the whole row here
@@ -138,12 +138,12 @@
/**
* Mount point info attributes.
*
- * @typedef {Object} OCA.External.MountPointInfo
+ * @typedef {Object} OCA.Files_External.MountPointInfo
*
* @property {String} name mount point name
* @property {String} scope mount point scope "personal" or "system"
* @property {String} backend external storage backend name
*/
- OCA.External.FileList = FileList;
+ OCA.Files_External.FileList = FileList;
})();
diff --git a/apps/files_external/js/oauth1.js b/apps/files_external/js/oauth1.js
index 79248a3e3b2..56e674b213b 100644
--- a/apps/files_external/js/oauth1.js
+++ b/apps/files_external/js/oauth1.js
@@ -4,7 +4,7 @@ $(document).ready(function() {
$tr.find('.configuration input.auth-param').attr('disabled', 'disabled').addClass('disabled-success');
}
- OCA.External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) {
+ OCA.Files_External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) {
if (authMechanism === 'oauth1::oauth1') {
var config = $tr.find('.configuration');
config.append($(document.createElement('input'))
@@ -34,7 +34,7 @@ $(document).ready(function() {
$(token).val(result.access_token);
$(token_secret).val(result.access_token_secret);
$(configured).val('true');
- OCA.External.Settings.mountConfig.saveStorageConfig($tr, function(status) {
+ OCA.Files_External.Settings.mountConfig.saveStorageConfig($tr, function(status) {
if (status) {
displayGranted($tr);
}
@@ -64,7 +64,7 @@ $(document).ready(function() {
$(configured).val('false');
$(token).val(result.data.request_token);
$(token_secret).val(result.data.request_token_secret);
- OCA.External.Settings.mountConfig.saveStorageConfig(tr, function() {
+ OCA.Files_External.Settings.mountConfig.saveStorageConfig(tr, function() {
window.location = result.data.url;
});
} else {
diff --git a/apps/files_external/js/oauth2.js b/apps/files_external/js/oauth2.js
index 13b5162694e..fb7160d6684 100644
--- a/apps/files_external/js/oauth2.js
+++ b/apps/files_external/js/oauth2.js
@@ -4,7 +4,7 @@ $(document).ready(function() {
$tr.find('.configuration input.auth-param').attr('disabled', 'disabled').addClass('disabled-success');
}
- OCA.External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) {
+ OCA.Files_External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) {
if (authMechanism === 'oauth2::oauth2') {
var config = $tr.find('.configuration');
config.append($(document.createElement('input'))
@@ -43,7 +43,7 @@ $(document).ready(function() {
if (result && result.status == 'success') {
$(token).val(result.data.token);
$(configured).val('true');
- OCA.External.Settings.mountConfig.saveStorageConfig($tr, function(status) {
+ OCA.Files_External.Settings.mountConfig.saveStorageConfig($tr, function(status) {
if (status) {
displayGranted($tr);
}
@@ -80,7 +80,7 @@ $(document).ready(function() {
if (result && result.status == 'success') {
$(configured).val('false');
$(token).val('false');
- OCA.External.Settings.mountConfig.saveStorageConfig(tr, function(status) {
+ OCA.Files_External.Settings.mountConfig.saveStorageConfig(tr, function(status) {
window.location = result.data.url;
});
} else {
diff --git a/apps/files_external/js/public_key.js b/apps/files_external/js/public_key.js
index 6856c7d021f..9b9ca6038c8 100644
--- a/apps/files_external/js/public_key.js
+++ b/apps/files_external/js/public_key.js
@@ -1,6 +1,6 @@
$(document).ready(function() {
- OCA.External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) {
+ OCA.Files_External.Settings.mountConfig.whenSelectAuthMechanism(function($tr, authMechanism, scheme, onCompletion) {
if (scheme === 'publickey' && authMechanism === 'publickey::rsa') {
var config = $tr.find('.configuration');
if ($(config).find('[name="public_key_generate"]').length === 0) {
@@ -53,7 +53,7 @@ $(document).ready(function() {
if (result && result.status === 'success') {
$(config).find('[data-parameter="public_key"]').val(result.data.public_key).keyup();
$(config).find('[data-parameter="private_key"]').val(result.data.private_key);
- OCA.External.Settings.mountConfig.saveStorageConfig(tr, function() {
+ OCA.Files_External.Settings.mountConfig.saveStorageConfig(tr, function() {
// Nothing to do
});
} else {
diff --git a/apps/files_external/js/rollingqueue.js b/apps/files_external/js/rollingqueue.js
index 53e11cb1219..df3797ada89 100644
--- a/apps/files_external/js/rollingqueue.js
+++ b/apps/files_external/js/rollingqueue.js
@@ -124,14 +124,14 @@ var RollingQueue = function (functionList, queueWindow, callback) {
};
};
-if (!OCA.External) {
- OCA.External = {};
+if (!OCA.Files_External) {
+ OCA.Files_External = {};
}
-if (!OCA.External.StatusManager) {
- OCA.External.StatusManager = {};
+if (!OCA.Files_External.StatusManager) {
+ OCA.Files_External.StatusManager = {};
}
-OCA.External.StatusManager.RollingQueue = RollingQueue;
+OCA.Files_External.StatusManager.RollingQueue = RollingQueue;
})();
diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js
index 2d495281527..adf3f766202 100644
--- a/apps/files_external/js/settings.js
+++ b/apps/files_external/js/settings.js
@@ -163,7 +163,7 @@ function addSelect2 ($elements, userListLimit) {
}
/**
- * @class OCA.External.Settings.StorageConfig
+ * @class OCA.Files_External.Settings.StorageConfig
*
* @classdesc External storage config
*/
@@ -185,7 +185,7 @@ StorageConfig.Visibility = {
DEFAULT: 3
};
/**
- * @memberof OCA.External.Settings
+ * @memberof OCA.Files_External.Settings
*/
StorageConfig.prototype = {
_url: null,
@@ -348,8 +348,8 @@ StorageConfig.prototype = {
};
/**
- * @class OCA.External.Settings.GlobalStorageConfig
- * @augments OCA.External.Settings.StorageConfig
+ * @class OCA.Files_External.Settings.GlobalStorageConfig
+ * @augments OCA.Files_External.Settings.StorageConfig
*
* @classdesc Global external storage config
*/
@@ -359,10 +359,10 @@ var GlobalStorageConfig = function(id) {
this.applicableGroups = [];
};
/**
- * @memberOf OCA.External.Settings
+ * @memberOf OCA.Files_External.Settings
*/
GlobalStorageConfig.prototype = _.extend({}, StorageConfig.prototype,
- /** @lends OCA.External.Settings.GlobalStorageConfig.prototype */ {
+ /** @lends OCA.Files_External.Settings.GlobalStorageConfig.prototype */ {
_url: 'apps/files_external/globalstorages',
/**
@@ -402,8 +402,8 @@ GlobalStorageConfig.prototype = _.extend({}, StorageConfig.prototype,
});
/**
- * @class OCA.External.Settings.UserStorageConfig
- * @augments OCA.External.Settings.StorageConfig
+ * @class OCA.Files_External.Settings.UserStorageConfig
+ * @augments OCA.Files_External.Settings.StorageConfig
*
* @classdesc User external storage config
*/
@@ -411,13 +411,13 @@ var UserStorageConfig = function(id) {
this.id = id;
};
UserStorageConfig.prototype = _.extend({}, StorageConfig.prototype,
- /** @lends OCA.External.Settings.UserStorageConfig.prototype */ {
+ /** @lends OCA.Files_External.Settings.UserStorageConfig.prototype */ {
_url: 'apps/files_external/userstorages'
});
/**
- * @class OCA.External.Settings.UserGlobalStorageConfig
- * @augments OCA.External.Settings.StorageConfig
+ * @class OCA.Files_External.Settings.UserGlobalStorageConfig
+ * @augments OCA.Files_External.Settings.StorageConfig
*
* @classdesc User external storage config
*/
@@ -425,13 +425,13 @@ var UserGlobalStorageConfig = function (id) {
this.id = id;
};
UserGlobalStorageConfig.prototype = _.extend({}, StorageConfig.prototype,
- /** @lends OCA.External.Settings.UserStorageConfig.prototype */ {
+ /** @lends OCA.Files_External.Settings.UserStorageConfig.prototype */ {
_url: 'apps/files_external/userglobalstorages'
});
/**
- * @class OCA.External.Settings.MountOptionsDropdown
+ * @class OCA.Files_External.Settings.MountOptionsDropdown
*
* @classdesc Dropdown for mount options
*
@@ -440,7 +440,7 @@ UserGlobalStorageConfig.prototype = _.extend({}, StorageConfig.prototype,
var MountOptionsDropdown = function() {
};
/**
- * @memberof OCA.External.Settings
+ * @memberof OCA.Files_External.Settings
*/
MountOptionsDropdown.prototype = {
/**
@@ -462,7 +462,7 @@ MountOptionsDropdown.prototype = {
MountOptionsDropdown._last.hide();
}
- var $el = $(OCA.External.Templates.mountOptionsDropDown({
+ var $el = $(OCA.Files_External.Templates.mountOptionsDropDown({
mountOptionsEncodingLabel: t('files_external', 'Compatibility with Mac NFD encoding (slow)'),
mountOptionsEncryptLabel: t('files_external', 'Enable encryption'),
mountOptionsPreviewsLabel: t('files_external', 'Enable previews'),
@@ -549,7 +549,7 @@ MountOptionsDropdown.prototype = {
};
/**
- * @class OCA.External.Settings.MountConfigListView
+ * @class OCA.Files_External.Settings.MountConfigListView
*
* @classdesc Mount configuration list view
*
@@ -574,7 +574,7 @@ MountConfigListView.ParameterTypes = {
};
/**
- * @memberOf OCA.External.Settings
+ * @memberOf OCA.Files_External.Settings
*/
MountConfigListView.prototype = _.extend({
@@ -633,9 +633,9 @@ MountConfigListView.prototype = _.extend({
this.$el = $el;
this._isPersonal = ($el.data('admin') !== true);
if (this._isPersonal) {
- this._storageConfigClass = OCA.External.Settings.UserStorageConfig;
+ this._storageConfigClass = OCA.Files_External.Settings.UserStorageConfig;
} else {
- this._storageConfigClass = OCA.External.Settings.GlobalStorageConfig;
+ this._storageConfigClass = OCA.Files_External.Settings.GlobalStorageConfig;
}
if (options && !_.isUndefined(options.userListLimit)) {
@@ -1008,7 +1008,7 @@ MountConfigListView.prototype = _.extend({
* Gets the storage model from the given row
*
* @param $tr row element
- * @return {OCA.External.StorageConfig} storage model instance
+ * @return {OCA.Files_External.StorageConfig} storage model instance
*/
getStorageConfig: function($tr) {
var storageId = $tr.data('id');
@@ -1367,13 +1367,13 @@ $(document).ready(function() {
});
// global instance
- OCA.External.Settings.mountConfig = mountConfigListView;
+ OCA.Files_External.Settings.mountConfig = mountConfigListView;
/**
* Legacy
*
* @namespace
- * @deprecated use OCA.External.Settings.mountConfig instead
+ * @deprecated use OCA.Files_External.Settings.mountConfig instead
*/
OC.MountConfig = {
saveStorage: _.bind(mountConfigListView.saveStorageConfig, mountConfigListView)
@@ -1382,14 +1382,14 @@ $(document).ready(function() {
// export
-OCA.External = OCA.External || {};
+OCA.Files_External = OCA.Files_External || {};
/**
* @namespace
*/
-OCA.External.Settings = OCA.External.Settings || {};
+OCA.Files_External.Settings = OCA.Files_External.Settings || {};
-OCA.External.Settings.GlobalStorageConfig = GlobalStorageConfig;
-OCA.External.Settings.UserStorageConfig = UserStorageConfig;
-OCA.External.Settings.MountConfigListView = MountConfigListView;
+OCA.Files_External.Settings.GlobalStorageConfig = GlobalStorageConfig;
+OCA.Files_External.Settings.UserStorageConfig = UserStorageConfig;
+OCA.Files_External.Settings.MountConfigListView = MountConfigListView;
})();
diff --git a/apps/files_external/js/statusmanager.js b/apps/files_external/js/statusmanager.js
index b8b5e1a9364..b4e89bd6232 100644
--- a/apps/files_external/js/statusmanager.js
+++ b/apps/files_external/js/statusmanager.js
@@ -14,15 +14,15 @@
/** @global Handlebars */
-if (!OCA.External) {
- OCA.External = {};
+if (!OCA.Files_External) {
+ OCA.Files_External = {};
}
-if (!OCA.External.StatusManager) {
- OCA.External.StatusManager = {};
+if (!OCA.Files_External.StatusManager) {
+ OCA.Files_External.StatusManager = {};
}
-OCA.External.StatusManager = {
+OCA.Files_External.StatusManager = {
mountStatus: null,
mountPointList: null,
@@ -209,18 +209,18 @@ OCA.External.StatusManager = {
var mountPoint = mountData.mount_point;
if (mountStatus.status > 0) {
- var trElement = FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(mountPoint));
+ var trElement = FileList.findFileEl(OCA.Files_External.StatusManager.Utils.jqSelEscape(mountPoint));
- var route = OCA.External.StatusManager.Utils.getIconRoute(trElement) + '-error';
+ var route = OCA.Files_External.StatusManager.Utils.getIconRoute(trElement) + '-error';
- if (OCA.External.StatusManager.Utils.isCorrectViewAndRootFolder()) {
- OCA.External.StatusManager.Utils.showIconError(mountPoint, $.proxy(OCA.External.StatusManager.manageMountPointError, OCA.External.StatusManager), route);
+ if (OCA.Files_External.StatusManager.Utils.isCorrectViewAndRootFolder()) {
+ OCA.Files_External.StatusManager.Utils.showIconError(mountPoint, $.proxy(OCA.Files_External.StatusManager.manageMountPointError, OCA.Files_External.StatusManager), route);
}
return false;
} else {
- if (OCA.External.StatusManager.Utils.isCorrectViewAndRootFolder()) {
- OCA.External.StatusManager.Utils.restoreFolder(mountPoint);
- OCA.External.StatusManager.Utils.toggleLink(mountPoint, true, true);
+ if (OCA.Files_External.StatusManager.Utils.isCorrectViewAndRootFolder()) {
+ OCA.Files_External.StatusManager.Utils.restoreFolder(mountPoint);
+ OCA.Files_External.StatusManager.Utils.toggleLink(mountPoint, true, true);
}
return true;
}
@@ -235,7 +235,7 @@ OCA.External.StatusManager = {
processMountList: function (mountList) {
var elementList = null;
$.each(mountList, function (name, value) {
- var trElement = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(value.mount_point) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(value.mount_point));
+ var trElement = $('#fileList tr[data-file=\"' + OCA.Files_External.StatusManager.Utils.jqSelEscape(value.mount_point) + '\"]'); //FileList.findFileEl(OCA.Files_External.StatusManager.Utils.jqSelEscape(value.mount_point));
trElement.attr('data-external-backend', value.backend);
if (elementList) {
elementList = elementList.add(trElement);
@@ -245,14 +245,14 @@ OCA.External.StatusManager = {
});
if (elementList instanceof $) {
- if (OCA.External.StatusManager.Utils.isCorrectViewAndRootFolder()) {
+ if (OCA.Files_External.StatusManager.Utils.isCorrectViewAndRootFolder()) {
// Put their custom icon
- OCA.External.StatusManager.Utils.changeFolderIcon(elementList);
+ OCA.Files_External.StatusManager.Utils.changeFolderIcon(elementList);
// Save default view
- OCA.External.StatusManager.Utils.storeDefaultFolderIconAndBgcolor(elementList);
+ OCA.Files_External.StatusManager.Utils.storeDefaultFolderIconAndBgcolor(elementList);
// Disable row until check status
elementList.addClass('externalDisabledRow');
- OCA.External.StatusManager.Utils.toggleLink(elementList.find('a.name'), false, false);
+ OCA.Files_External.StatusManager.Utils.toggleLink(elementList.find('a.name'), false, false);
}
}
},
@@ -289,7 +289,7 @@ OCA.External.StatusManager = {
ajaxQueue.push(queueElement);
});
- var rolQueue = new OCA.External.StatusManager.RollingQueue(ajaxQueue, 4, function () {
+ var rolQueue = new OCA.Files_External.StatusManager.RollingQueue(ajaxQueue, 4, function () {
if (!self.notificationHasShown) {
var showNotification = false;
$.each(self.mountStatus, function (key, value) {
@@ -335,7 +335,7 @@ OCA.External.StatusManager = {
};
ajaxQueue.push(queueElement);
});
- new OCA.External.StatusManager.RollingQueue(ajaxQueue, 4).runQueue();
+ new OCA.Files_External.StatusManager.RollingQueue(ajaxQueue, 4).runQueue();
},
@@ -392,7 +392,7 @@ OCA.External.StatusManager = {
* @param mountData
*/
showCredentialsDialog: function (mountPoint, mountData) {
- var dialog = $(OCA.External.Templates.credentialsDialog({
+ var dialog = $(OCA.Files_External.Templates.credentialsDialog({
credentials_text: t('files_external', 'Please enter the credentials for the {mount} mount', {
'mount': mountPoint
}),
@@ -422,7 +422,7 @@ OCA.External.StatusManager = {
OC.Notification.show(t('files_external', 'Credentials saved'), {type: 'error'});
dialog.ocdialog('close');
/* Trigger status check again */
- OCA.External.StatusManager.recheckConnectivityForMount([OC.basename(data.mountPoint)], true);
+ OCA.Files_External.StatusManager.recheckConnectivityForMount([OC.basename(data.mountPoint)], true);
},
error: function () {
$('.oc-dialog-close').show();
@@ -461,11 +461,11 @@ OCA.External.StatusManager = {
}
};
-OCA.External.StatusManager.Utils = {
+OCA.Files_External.StatusManager.Utils = {
showIconError: function (folder, clickAction, errorImageUrl) {
var imageUrl = "url(" + errorImageUrl + ")";
- var trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder));
+ var trFolder = $('#fileList tr[data-file=\"' + OCA.Files_External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.Files_External.StatusManager.Utils.jqSelEscape(folder));
this.changeFolderIcon(folder, imageUrl);
this.toggleLink(folder, false, clickAction);
trFolder.addClass('externalErroredRow');
@@ -479,7 +479,7 @@ OCA.External.StatusManager.Utils = {
if (folder instanceof $) {
trFolder = folder;
} else {
- trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder)); //$('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]');
+ trFolder = $('#fileList tr[data-file=\"' + OCA.Files_External.StatusManager.Utils.jqSelEscape(folder) + '\"]'); //FileList.findFileEl(OCA.Files_External.StatusManager.Utils.jqSelEscape(folder)); //$('#fileList tr[data-file=\"' + OCA.Files_External.StatusManager.Utils.jqSelEscape(folder) + '\"]');
}
trFolder.each(function () {
var thisElement = $(this);
@@ -505,8 +505,8 @@ OCA.External.StatusManager.Utils = {
if (folder instanceof $) {
trFolder = folder;
} else {
- // can't use here FileList.findFileEl(OCA.External.StatusManager.Utils.jqSelEscape(folder)); return incorrect instance of filelist
- trFolder = $('#fileList tr[data-file=\"' + OCA.External.StatusManager.Utils.jqSelEscape(folder) + '\"]');
+ // can't use here FileList.findFileEl(OCA.Files_External.StatusManager.Utils.jqSelEscape(folder)); return incorrect instance of filelist
+ trFolder = $('#fileList tr[data-file=\"' + OCA.Files_External.StatusManager.Utils.jqSelEscape(folder) + '\"]');
}
trFolder.removeClass('externalErroredRow').removeClass('externalDisabledRow');
var tdChilds = trFolder.find("td.filename div.thumbnail");
@@ -526,14 +526,14 @@ OCA.External.StatusManager.Utils = {
if (filename instanceof $) {
//trElementList
$.each(filename, function (index) {
- route = OCA.External.StatusManager.Utils.getIconRoute($(this));
+ route = OCA.Files_External.StatusManager.Utils.getIconRoute($(this));
$(this).attr("data-icon", route);
$(this).find('td.filename div.thumbnail').css('background-image', "url(" + route + ")").css('display', 'none').css('display', 'inline');
});
} else {
file = $("#fileList tr[data-file=\"" + this.jqSelEscape(filename) + "\"] > td.filename div.thumbnail");
var parentTr = file.parents('tr:first');
- route = OCA.External.StatusManager.Utils.getIconRoute(parentTr);
+ route = OCA.Files_External.StatusManager.Utils.getIconRoute(parentTr);
parentTr.attr("data-icon", route);
file.css('background-image', "url(" + route + ")").css('display', 'none').css('display', 'inline');
}
diff --git a/apps/files_external/js/templates.js b/apps/files_external/js/templates.js
index 067b3f5f5d7..cf1522334c5 100644
--- a/apps/files_external/js/templates.js
+++ b/apps/files_external/js/templates.js
@@ -1,5 +1,5 @@
(function() {
- var template = Handlebars.template, templates = OCA.External.Templates = OCA.External.Templates || {};
+ var template = Handlebars.template, templates = OCA.Files_External.Templates = OCA.Files_External.Templates || {};
templates['credentialsDialog'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) {
var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression;
diff --git a/apps/files_external/tests/appSpec.js b/apps/files_external/tests/appSpec.js
index 43902d1c1d0..a834d96e2c0 100644
--- a/apps/files_external/tests/appSpec.js
+++ b/apps/files_external/tests/appSpec.js
@@ -19,8 +19,8 @@
*
*/
-describe('OCA.External.App tests', function() {
- var App = OCA.External.App;
+describe('OCA.Files_External.App tests', function() {
+ var App = OCA.Files_External.App;
var fileList;
beforeEach(function() {
diff --git a/apps/files_external/tests/js/mountsfilelistSpec.js b/apps/files_external/tests/js/mountsfilelistSpec.js
index feea68cf346..fe2fd8dec84 100644
--- a/apps/files_external/tests/js/mountsfilelistSpec.js
+++ b/apps/files_external/tests/js/mountsfilelistSpec.js
@@ -8,7 +8,7 @@
*
*/
-describe('OCA.External.FileList tests', function() {
+describe('OCA.Files_External.FileList tests', function() {
var testFiles, alertStub, notificationStub, fileList;
beforeEach(function() {
@@ -62,7 +62,7 @@ describe('OCA.External.FileList tests', function() {
var ocsResponse;
beforeEach(function() {
- fileList = new OCA.External.FileList(
+ fileList = new OCA.Files_External.FileList(
$('#app-content-container')
);
diff --git a/apps/files_external/tests/js/settingsSpec.js b/apps/files_external/tests/js/settingsSpec.js
index 57ad4550993..e004871650c 100644
--- a/apps/files_external/tests/js/settingsSpec.js
+++ b/apps/files_external/tests/js/settingsSpec.js
@@ -8,7 +8,7 @@
*
*/
-describe('OCA.External.Settings tests', function() {
+describe('OCA.Files_External.Settings tests', function() {
var clock;
var select2Stub;
var select2ApplicableUsers;
@@ -156,7 +156,7 @@ describe('OCA.External.Settings tests', function() {
beforeEach(function() {
var $el = $('#externalStorage');
- view = new OCA.External.Settings.MountConfigListView($el, {encryptionEnabled: false});
+ view = new OCA.Files_External.Settings.MountConfigListView($el, {encryptionEnabled: false});
});
afterEach(function() {
view = null;
diff --git a/apps/files_sharing/css/sharetabview.scss b/apps/files_sharing/css/sharetabview.scss
index 14be9562228..0d277c58bd7 100644
--- a/apps/files_sharing/css/sharetabview.scss
+++ b/apps/files_sharing/css/sharetabview.scss
@@ -4,6 +4,10 @@
.share-autocomplete-item {
display: flex;
+
+ &.merged {
+ margin-left: 32px;
+ }
.autocomplete-item-text {
margin-left: 10px;
margin-right: 10px;
@@ -12,6 +16,27 @@
overflow: hidden;
line-height: 32px;
vertical-align: middle;
+ flex-grow: 1;
+ .ui-state-highlight {
+ border: none;
+ margin: 0;
+ }
+ }
+ &.with-description {
+ .autocomplete-item-text {
+ line-height: 100%;
+ }
+ }
+ .autocomplete-item-details {
+ display: block;
+ line-height: 130%;
+ font-size: 90%;
+ opacity: 0.7;
+ }
+
+ .icon {
+ opacity: .7;
+ margin-right: 7px;
}
}
@@ -204,8 +229,8 @@
}
.ui-autocomplete {
- /* limit dropdown height to 4 1/2 entries */
- max-height: calc(36px * 4.5);;
+ /* limit dropdown height to 6 1/2 entries */
+ max-height: calc(36px * 6.5);
overflow-y: auto;
overflow-x: hidden;
z-index: 1550 !important;
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index ff19c35e2b5..a935189491e 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -252,6 +252,7 @@ class ShareAPIController extends OCSController {
$result['mail_send'] = $share->getMailSend() ? 1 : 0;
+ $result['hide_download'] = $share->getHideDownload() ? 1 : 0;
return $result;
}
@@ -745,6 +746,7 @@ class ShareAPIController extends OCSController {
* @param string $publicUpload
* @param string $expireDate
* @param string $note
+ * @param string $hideDownload
* @return DataResponse
* @throws LockedException
* @throws NotFoundException
@@ -759,7 +761,8 @@ class ShareAPIController extends OCSController {
string $sendPasswordByTalk = null,
string $publicUpload = null,
string $expireDate = null,
- string $note = null
+ string $note = null,
+ string $hideDownload = null
): DataResponse {
try {
$share = $this->getShareById($id);
@@ -773,7 +776,7 @@ class ShareAPIController extends OCSController {
throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
}
- if ($permissions === null && $password === null && $sendPasswordByTalk === null && $publicUpload === null && $expireDate === null && $note === null) {
+ if ($permissions === null && $password === null && $sendPasswordByTalk === null && $publicUpload === null && $expireDate === null && $note === null && $hideDownload === null) {
throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
}
@@ -786,6 +789,13 @@ class ShareAPIController extends OCSController {
*/
if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
+ // Update hide download state
+ if ($hideDownload === 'true') {
+ $share->setHideDownload(true);
+ } else if ($hideDownload === 'false') {
+ $share->setHideDownload(false);
+ }
+
$newPermissions = null;
if ($publicUpload === 'true') {
$newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
diff --git a/apps/files_sharing/lib/Controller/ShareController.php b/apps/files_sharing/lib/Controller/ShareController.php
index 1e3cbb51028..1a92000a5f6 100644
--- a/apps/files_sharing/lib/Controller/ShareController.php
+++ b/apps/files_sharing/lib/Controller/ShareController.php
@@ -321,6 +321,7 @@ class ShareController extends AuthPublicShareController {
$shareTmpl['dir'] = '';
$shareTmpl['nonHumanFileSize'] = $share->getNode()->getSize();
$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize());
+ $shareTmpl['hideDownload'] = $share->getHideDownload();
// Show file list
$hideFileList = false;
@@ -444,12 +445,14 @@ class ShareController extends AuthPublicShareController {
$response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
$response->setHeaderTitle($shareTmpl['filename']);
$response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['displayName']]));
- $response->setHeaderActions([
- new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0),
- new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']),
- new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']),
- new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['displayName'], $shareTmpl['filename']),
- ]);
+ if (!$share->getHideDownload()) {
+ $response->setHeaderActions([
+ new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0),
+ new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']),
+ new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']),
+ new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['displayName'], $shareTmpl['filename']),
+ ]);
+ }
$response->setContentSecurityPolicy($csp);
diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php
index da80f8d1377..4487e63f2de 100644
--- a/apps/files_sharing/templates/public.php
+++ b/apps/files_sharing/templates/public.php
@@ -11,13 +11,16 @@
<input type="hidden" id="filesApp" name="filesApp" value="1">
<input type="hidden" id="isPublic" name="isPublic" value="1">
<input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir">
-<input type="hidden" name="downloadURL" value="<?php p($_['downloadURL']) ?>" id="downloadURL">
+<?php if (!$_['hideDownload']): ?>
+ <input type="hidden" name="downloadURL" value="<?php p($_['downloadURL']) ?>" id="downloadURL">
+<?php endif; ?>
<input type="hidden" name="previewURL" value="<?php p($_['previewURL']) ?>" id="previewURL">
<input type="hidden" name="sharingToken" value="<?php p($_['sharingToken']) ?>" id="sharingToken">
<input type="hidden" name="filename" value="<?php p($_['filename']) ?>" id="filename">
<input type="hidden" name="mimetype" value="<?php p($_['mimetype']) ?>" id="mimetype">
<input type="hidden" name="previewSupported" value="<?php p($_['previewSupported'] ? 'true' : 'false'); ?>" id="previewSupported">
<input type="hidden" name="mimetypeIcon" value="<?php p(\OC::$server->getMimeTypeDetector()->mimeTypeIcon($_['mimetype'])); ?>" id="mimetypeIcon">
+<input type="hidden" name="hideDownload" value="<?php p($_['hideDownload'] ? 'true' : 'false'); ?>" id="hideDownload">
<?php
$upload_max_filesize = OC::$server->getIniWrapper()->getBytes('upload_max_filesize');
$post_max_size = OC::$server->getIniWrapper()->getBytes('post_max_size');
@@ -58,7 +61,7 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size);
<!-- Preview frame is filled via JS to support SVG images for modern browsers -->
<div id="imgframe"></div>
<?php endif; ?>
- <?php if ($_['previewURL'] === $_['downloadURL']): ?>
+ <?php if ($_['previewURL'] === $_['downloadURL'] && !$_['hideDownload']): ?>
<div class="directDownload">
<a href="<?php p($_['downloadURL']); ?>" id="downloadFile" class="button">
<span class="icon icon-download"></span>
@@ -97,4 +100,4 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size);
data-url="<?php p(\OC::$server->getURLGenerator()->linkTo('files', 'ajax/upload.php')); ?>" />
</div>
<?php endif; ?>
-</div> \ No newline at end of file
+</div>
diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
index 15c4071bc46..bd263de3f62 100644
--- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
@@ -353,6 +353,7 @@ class ShareAPIControllerTest extends TestCase {
'note' => 'personal note',
'displayname_file_owner' => 'ownerDisplay',
'mimetype' => 'myMimeType',
+ 'hide_download' => 0,
];
$data[] = [$share, $expected];
@@ -397,6 +398,7 @@ class ShareAPIControllerTest extends TestCase {
'note' => 'personal note',
'displayname_file_owner' => 'ownerDisplay',
'mimetype' => 'myFolderMimeType',
+ 'hide_download' => 0,
];
$data[] = [$share, $expected];
@@ -445,6 +447,7 @@ class ShareAPIControllerTest extends TestCase {
'note' => 'personal note',
'displayname_file_owner' => 'ownerDisplay',
'mimetype' => 'myFolderMimeType',
+ 'hide_download' => 0,
];
$data[] = [$share, $expected];
@@ -2175,6 +2178,7 @@ class ShareAPIControllerTest extends TestCase {
'note' => 'personal note',
'mail_send' => 0,
'mimetype' => 'myMimeType',
+ 'hide_download' => 0,
], $share, [], false
];
// User backend up
@@ -2204,6 +2208,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_displayname' => 'recipientDN',
'mail_send' => 0,
'mimetype' => 'myMimeType',
+ 'hide_download' => 0,
], $share, [
['owner', $owner],
['initiator', $initiator],
@@ -2249,6 +2254,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_displayname' => 'recipient',
'mail_send' => 0,
'mimetype' => 'myMimeType',
+ 'hide_download' => 0,
], $share, [], false
];
@@ -2292,6 +2298,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_displayname' => 'recipientGroupDisplayName',
'mail_send' => 0,
'mimetype' => 'myMimeType',
+ 'hide_download' => 0,
], $share, [], false
];
@@ -2333,6 +2340,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_displayname' => 'recipientGroup2',
'mail_send' => 0,
'mimetype' => 'myMimeType',
+ 'hide_download' => 0,
], $share, [], false
];
@@ -2377,6 +2385,7 @@ class ShareAPIControllerTest extends TestCase {
'mail_send' => 0,
'url' => 'myLink',
'mimetype' => 'myMimeType',
+ 'hide_download' => 0,
], $share, [], false
];
@@ -2418,6 +2427,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_displayname' => 'foobar',
'mail_send' => 0,
'mimetype' => 'myFolderMimeType',
+ 'hide_download' => 0,
], $share, [], false
];
@@ -2462,6 +2472,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_avatar' => 'path/to/the/avatar',
'mail_send' => 0,
'mimetype' => 'myFolderMimeType',
+ 'hide_download' => 0,
], $share, [], false
];
@@ -2504,6 +2515,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_avatar' => '',
'mail_send' => 0,
'mimetype' => 'myFolderMimeType',
+ 'hide_download' => 0,
], $share, [], false
];
@@ -2546,6 +2558,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_avatar' => '',
'mail_send' => 0,
'mimetype' => 'myFolderMimeType',
+ 'hide_download' => 0,
], $share, [], false
];
@@ -2603,7 +2616,8 @@ class ShareAPIControllerTest extends TestCase {
'mail_send' => 0,
'mimetype' => 'myFolderMimeType',
'password' => 'password',
- 'send_password_by_talk' => false
+ 'send_password_by_talk' => false,
+ 'hide_download' => 0,
], $share, [], false
];
@@ -2647,7 +2661,8 @@ class ShareAPIControllerTest extends TestCase {
'mail_send' => 0,
'mimetype' => 'myFolderMimeType',
'password' => 'password',
- 'send_password_by_talk' => true
+ 'send_password_by_talk' => true,
+ 'hide_download' => 0,
], $share, [], false
];
@@ -2787,6 +2802,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_displayname' => '',
'mail_send' => 0,
'mimetype' => 'myMimeType',
+ 'hide_download' => 0,
], $share, false, []
];
@@ -2828,6 +2844,7 @@ class ShareAPIControllerTest extends TestCase {
'share_with_displayname' => 'recipientRoomName',
'mail_send' => 0,
'mimetype' => 'myMimeType',
+ 'hide_download' => 0,
], $share, true, [
'share_with_displayname' => 'recipientRoomName'
]
diff --git a/apps/files_sharing/tests/Controller/ShareControllerTest.php b/apps/files_sharing/tests/Controller/ShareControllerTest.php
index a01560d0288..c5306cbc0ce 100644
--- a/apps/files_sharing/tests/Controller/ShareControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareControllerTest.php
@@ -287,7 +287,8 @@ class ShareControllerTest extends \Test\TestCase {
'shareUrl' => null,
'previewImage' => null,
'previewURL' => 'downloadURL',
- 'note' => $note
+ 'note' => $note,
+ 'hideDownload' => false
);
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
@@ -306,6 +307,120 @@ class ShareControllerTest extends \Test\TestCase {
$this->assertEquals($expectedResponse, $response);
}
+ public function testShowShareHideDownload() {
+ $note = 'personal note';
+
+ $this->shareController->setToken('token');
+
+ $owner = $this->getMockBuilder(IUser::class)->getMock();
+ $owner->method('getDisplayName')->willReturn('ownerDisplay');
+ $owner->method('getUID')->willReturn('ownerUID');
+
+ $file = $this->getMockBuilder('OCP\Files\File')->getMock();
+ $file->method('getName')->willReturn('file1.txt');
+ $file->method('getMimetype')->willReturn('text/plain');
+ $file->method('getSize')->willReturn(33);
+ $file->method('isReadable')->willReturn(true);
+ $file->method('isShareable')->willReturn(true);
+
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setId(42);
+ $share->setPassword('password')
+ ->setShareOwner('ownerUID')
+ ->setNode($file)
+ ->setNote($note)
+ ->setTarget('/file1.txt')
+ ->setHideDownload(true);
+
+ $this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
+ $this->session->method('get')->with('public_link_authenticated')->willReturn('42');
+
+ // Even if downloads are disabled the "downloadURL" parameter is
+ // provided to the template, as it is needed to preview audio and GIF
+ // files.
+ $this->urlGenerator->expects($this->at(0))
+ ->method('linkToRouteAbsolute')
+ ->with('files_sharing.sharecontroller.downloadShare', ['token' => 'token'])
+ ->willReturn('downloadURL');
+
+ $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true);
+
+ $this->config->method('getSystemValue')
+ ->willReturnMap(
+ [
+ ['max_filesize_animated_gifs_public_sharing', 10, 10],
+ ['enable_previews', true, true],
+ ['preview_max_x', 1024, 1024],
+ ['preview_max_y', 1024, 1024],
+ ]
+ );
+ $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
+ $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
+
+ $this->shareManager
+ ->expects($this->once())
+ ->method('getShareByToken')
+ ->with('token')
+ ->willReturn($share);
+ $this->config
+ ->expects($this->once())
+ ->method('getAppValue')
+ ->with('core', 'shareapi_public_link_disclaimertext', null)
+ ->willReturn('My disclaimer text');
+
+ $this->userManager->method('get')->with('ownerUID')->willReturn($owner);
+
+ $this->eventDispatcher->expects($this->once())
+ ->method('dispatch')
+ ->with('OCA\Files_Sharing::loadAdditionalScripts');
+
+ $this->l10n->expects($this->any())
+ ->method('t')
+ ->will($this->returnCallback(function($text, $parameters) {
+ return vsprintf($text, $parameters);
+ }));
+
+ $response = $this->shareController->showShare();
+ $sharedTmplParams = array(
+ 'displayName' => 'ownerDisplay',
+ 'owner' => 'ownerUID',
+ 'filename' => 'file1.txt',
+ 'directory_path' => '/file1.txt',
+ 'mimetype' => 'text/plain',
+ 'dirToken' => 'token',
+ 'sharingToken' => 'token',
+ 'server2serversharing' => true,
+ 'protected' => 'true',
+ 'dir' => '',
+ 'downloadURL' => 'downloadURL',
+ 'fileSize' => '33 B',
+ 'nonHumanFileSize' => 33,
+ 'maxSizeAnimateGif' => 10,
+ 'previewSupported' => true,
+ 'previewEnabled' => true,
+ 'previewMaxX' => 1024,
+ 'previewMaxY' => 1024,
+ 'hideFileList' => false,
+ 'shareOwner' => 'ownerDisplay',
+ 'disclaimer' => 'My disclaimer text',
+ 'shareUrl' => null,
+ 'previewImage' => null,
+ 'previewURL' => 'downloadURL',
+ 'note' => $note,
+ 'hideDownload' => true
+ );
+
+ $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
+ $csp->addAllowedFrameDomain('\'self\'');
+ $expectedResponse = new PublicTemplateResponse($this->appName, 'public', $sharedTmplParams);
+ $expectedResponse->setContentSecurityPolicy($csp);
+ $expectedResponse->setHeaderTitle($sharedTmplParams['filename']);
+ $expectedResponse->setHeaderDetails('shared by ' . $sharedTmplParams['displayName']);
+ $expectedResponse->setHeaderActions([]);
+
+ $this->assertEquals($expectedResponse, $response);
+ }
+
/**
* @expectedException \OCP\Files\NotFoundException
*/
diff --git a/apps/files_versions/appinfo/info.xml b/apps/files_versions/appinfo/info.xml
index d2f873edb07..6d1b3085f80 100644
--- a/apps/files_versions/appinfo/info.xml
+++ b/apps/files_versions/appinfo/info.xml
@@ -41,4 +41,8 @@
<collection>OCA\Files_Versions\Sabre\RootCollection</collection>
</collections>
</sabre>
+
+ <versions>
+ <backend for="OCP\Files\Storage\IStorage">OCA\Files_Versions\Versions\LegacyVersionsBackend</backend>
+ </versions>
</info>
diff --git a/apps/files_versions/composer/composer/autoload_classmap.php b/apps/files_versions/composer/composer/autoload_classmap.php
index 4bb112b4f11..1283e533914 100644
--- a/apps/files_versions/composer/composer/autoload_classmap.php
+++ b/apps/files_versions/composer/composer/autoload_classmap.php
@@ -23,4 +23,11 @@ return array(
'OCA\\Files_Versions\\Sabre\\VersionHome' => $baseDir . '/../lib/Sabre/VersionHome.php',
'OCA\\Files_Versions\\Sabre\\VersionRoot' => $baseDir . '/../lib/Sabre/VersionRoot.php',
'OCA\\Files_Versions\\Storage' => $baseDir . '/../lib/Storage.php',
+ 'OCA\\Files_Versions\\Versions\\BackendNotFoundException' => $baseDir . '/../lib/Versions/BackendNotFoundException.php',
+ 'OCA\\Files_Versions\\Versions\\IVersion' => $baseDir . '/../lib/Versions/IVersion.php',
+ 'OCA\\Files_Versions\\Versions\\IVersionBackend' => $baseDir . '/../lib/Versions/IVersionBackend.php',
+ 'OCA\\Files_Versions\\Versions\\IVersionManager' => $baseDir . '/../lib/Versions/IVersionManager.php',
+ 'OCA\\Files_Versions\\Versions\\LegacyVersionsBackend' => $baseDir . '/../lib/Versions/LegacyVersionsBackend.php',
+ 'OCA\\Files_Versions\\Versions\\Version' => $baseDir . '/../lib/Versions/Version.php',
+ 'OCA\\Files_Versions\\Versions\\VersionManager' => $baseDir . '/../lib/Versions/VersionManager.php',
);
diff --git a/apps/files_versions/composer/composer/autoload_static.php b/apps/files_versions/composer/composer/autoload_static.php
index 29bc592b41c..6a6b753c2e5 100644
--- a/apps/files_versions/composer/composer/autoload_static.php
+++ b/apps/files_versions/composer/composer/autoload_static.php
@@ -38,6 +38,13 @@ class ComposerStaticInitFiles_Versions
'OCA\\Files_Versions\\Sabre\\VersionHome' => __DIR__ . '/..' . '/../lib/Sabre/VersionHome.php',
'OCA\\Files_Versions\\Sabre\\VersionRoot' => __DIR__ . '/..' . '/../lib/Sabre/VersionRoot.php',
'OCA\\Files_Versions\\Storage' => __DIR__ . '/..' . '/../lib/Storage.php',
+ 'OCA\\Files_Versions\\Versions\\BackendNotFoundException' => __DIR__ . '/..' . '/../lib/Versions/BackendNotFoundException.php',
+ 'OCA\\Files_Versions\\Versions\\IVersion' => __DIR__ . '/..' . '/../lib/Versions/IVersion.php',
+ 'OCA\\Files_Versions\\Versions\\IVersionBackend' => __DIR__ . '/..' . '/../lib/Versions/IVersionBackend.php',
+ 'OCA\\Files_Versions\\Versions\\IVersionManager' => __DIR__ . '/..' . '/../lib/Versions/IVersionManager.php',
+ 'OCA\\Files_Versions\\Versions\\LegacyVersionsBackend' => __DIR__ . '/..' . '/../lib/Versions/LegacyVersionsBackend.php',
+ 'OCA\\Files_Versions\\Versions\\Version' => __DIR__ . '/..' . '/../lib/Versions/Version.php',
+ 'OCA\\Files_Versions\\Versions\\VersionManager' => __DIR__ . '/..' . '/../lib/Versions/VersionManager.php',
);
public static function getInitializer(ClassLoader $loader)
diff --git a/apps/files_versions/js/versionstabview.js b/apps/files_versions/js/versionstabview.js
index 61309a30d50..213ee1ae83c 100644
--- a/apps/files_versions/js/versionstabview.js
+++ b/apps/files_versions/js/versionstabview.js
@@ -38,6 +38,10 @@
return t('files_versions', 'Versions');
},
+ getIcon: function() {
+ return 'icon-history';
+ },
+
nextPage: function() {
if (this._loading) {
return;
diff --git a/apps/files_versions/lib/AppInfo/Application.php b/apps/files_versions/lib/AppInfo/Application.php
index 340b5ab5cbd..935556221fa 100644
--- a/apps/files_versions/lib/AppInfo/Application.php
+++ b/apps/files_versions/lib/AppInfo/Application.php
@@ -24,9 +24,10 @@
namespace OCA\Files_Versions\AppInfo;
use OCA\DAV\Connector\Sabre\Principal;
+use OCA\Files_Versions\Versions\IVersionManager;
+use OCA\Files_Versions\Versions\VersionManager;
use OCP\AppFramework\App;
-use OCA\Files_Versions\Expiration;
-use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\AppFramework\IAppContainer;
use OCA\Files_Versions\Capabilities;
class Application extends App {
@@ -43,14 +44,45 @@ class Application extends App {
/*
* Register $principalBackend for the DAV collection
*/
- $container->registerService('principalBackend', function () {
+ $container->registerService('principalBackend', function (IAppContainer $c) {
+ $server = $c->getServer();
return new Principal(
- \OC::$server->getUserManager(),
- \OC::$server->getGroupManager(),
- \OC::$server->getShareManager(),
- \OC::$server->getUserSession(),
- \OC::$server->getConfig()
+ $server->getUserManager(),
+ $server->getGroupManager(),
+ $server->getShareManager(),
+ $server->getUserSession(),
+ $server->getConfig()
);
});
+
+ $container->registerService(IVersionManager::class, function(IAppContainer $c) {
+ return new VersionManager();
+ });
+
+ $this->registerVersionBackends();
+ }
+
+ public function registerVersionBackends() {
+ $server = $this->getContainer()->getServer();
+ $logger = $server->getLogger();
+ $appManager = $server->getAppManager();
+ /** @var IVersionManager $versionManager */
+ $versionManager = $this->getContainer()->getServer()->query(IVersionManager::class);
+ foreach($appManager->getInstalledApps() as $app) {
+ $appInfo = $appManager->getAppInfo($app);
+ if (isset($appInfo['versions'])) {
+ $backends = $appInfo['versions'];
+ foreach($backends as $backend) {
+ $class = $backend['@value'];
+ $for = $backend['@attributes']['for'];
+ try {
+ $backendObject = $server->query($class);
+ $versionManager->registerBackend($for, $backendObject);
+ } catch (\Exception $e) {
+ $logger->logException($e);
+ }
+ }
+ }
+ }
}
}
diff --git a/apps/files_versions/lib/Controller/PreviewController.php b/apps/files_versions/lib/Controller/PreviewController.php
index b8bf464fb3f..f41250a8971 100644
--- a/apps/files_versions/lib/Controller/PreviewController.php
+++ b/apps/files_versions/lib/Controller/PreviewController.php
@@ -21,45 +21,53 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OCA\Files_Versions\Controller;
+use OCA\Files_Versions\Versions\IVersionManager;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\FileDisplayResponse;
-use OCP\Files\File;
-use OCP\Files\Folder;
use OCP\Files\IMimeTypeDetector;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IPreview;
use OCP\IRequest;
+use OCP\IUserSession;
class PreviewController extends Controller {
/** @var IRootFolder */
private $rootFolder;
- /** @var string */
- private $userId;
+ /** @var IUserSession */
+ private $userSession;
/** @var IMimeTypeDetector */
private $mimeTypeDetector;
+ /** @var IVersionManager */
+ private $versionManager;
+
/** @var IPreview */
private $previewManager;
- public function __construct($appName,
- IRequest $request,
- IRootFolder $rootFolder,
- $userId,
- IMimeTypeDetector $mimeTypeDetector,
- IPreview $previewManager) {
+ public function __construct(
+ $appName,
+ IRequest $request,
+ IRootFolder $rootFolder,
+ IUserSession $userSession,
+ IMimeTypeDetector $mimeTypeDetector,
+ IVersionManager $versionManager,
+ IPreview $previewManager
+ ) {
parent::__construct($appName, $request);
$this->rootFolder = $rootFolder;
- $this->userId = $userId;
+ $this->userSession = $userSession;
$this->mimeTypeDetector = $mimeTypeDetector;
+ $this->versionManager = $versionManager;
$this->previewManager = $previewManager;
}
@@ -79,20 +87,17 @@ class PreviewController extends Controller {
$y = 44,
$version = ''
) {
- if($file === '' || $version === '' || $x === 0 || $y === 0) {
+ if ($file === '' || $version === '' || $x === 0 || $y === 0) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
try {
- $userFolder = $this->rootFolder->getUserFolder($this->userId);
- /** @var Folder $versionFolder */
- $versionFolder = $userFolder->getParent()->get('files_versions');
- $mimeType = $this->mimeTypeDetector->detectPath($file);
- $file = $versionFolder->get($file.'.v'.$version);
-
- /** @var File $file */
- $f = $this->previewManager->getPreview($file, $x, $y, true, IPreview::MODE_FILL, $mimeType);
- return new FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
+ $user = $this->userSession->getUser();
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $file = $userFolder->get($file);
+ $versionFile = $this->versionManager->getVersionFile($user, $file, (int)$version);
+ $preview = $this->previewManager->getPreview($versionFile, $x, $y, true, IPreview::MODE_FILL, $versionFile->getMimetype());
+ return new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => $preview->getMimeType()]);
} catch (NotFoundException $e) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
} catch (\InvalidArgumentException $e) {
diff --git a/apps/files_versions/lib/Sabre/RestoreFolder.php b/apps/files_versions/lib/Sabre/RestoreFolder.php
index c398d02692b..c8504646bad 100644
--- a/apps/files_versions/lib/Sabre/RestoreFolder.php
+++ b/apps/files_versions/lib/Sabre/RestoreFolder.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace OCA\Files_Versions\Sabre;
+use OCP\IUser;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\ICollection;
use Sabre\DAV\IMoveTarget;
@@ -31,14 +32,6 @@ use Sabre\DAV\INode;
class RestoreFolder implements ICollection, IMoveTarget {
-
- /** @var string */
- protected $userId;
-
- public function __construct(string $userId) {
- $this->userId = $userId;
- }
-
public function createFile($name, $data = null) {
throw new Forbidden();
}
@@ -80,7 +73,8 @@ class RestoreFolder implements ICollection, IMoveTarget {
return false;
}
- return $sourceNode->rollBack();
+ $sourceNode->rollBack();
+ return true;
}
}
diff --git a/apps/files_versions/lib/Sabre/RootCollection.php b/apps/files_versions/lib/Sabre/RootCollection.php
index ca5979573b5..504c3362505 100644
--- a/apps/files_versions/lib/Sabre/RootCollection.php
+++ b/apps/files_versions/lib/Sabre/RootCollection.php
@@ -20,10 +20,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OCA\Files_Versions\Sabre;
+use OCA\Files_Versions\Versions\IVersionManager;
use OCP\Files\IRootFolder;
use OCP\IConfig;
+use OCP\IUserManager;
use Sabre\DAV\INode;
use Sabre\DAVACL\AbstractPrincipalCollection;
use Sabre\DAVACL\PrincipalBackend;
@@ -33,12 +36,24 @@ class RootCollection extends AbstractPrincipalCollection {
/** @var IRootFolder */
private $rootFolder;
- public function __construct(PrincipalBackend\BackendInterface $principalBackend,
- IRootFolder $rootFolder,
- IConfig $config) {
+ /** @var IUserManager */
+ private $userManager;
+
+ /** @var IVersionManager */
+ private $versionManager;
+
+ public function __construct(
+ PrincipalBackend\BackendInterface $principalBackend,
+ IRootFolder $rootFolder,
+ IConfig $config,
+ IUserManager $userManager,
+ IVersionManager $versionManager
+ ) {
parent::__construct($principalBackend, 'principals/users');
$this->rootFolder = $rootFolder;
+ $this->userManager = $userManager;
+ $this->versionManager = $versionManager;
$this->disableListing = !$config->getSystemValue('debug', false);
}
@@ -54,12 +69,12 @@ class RootCollection extends AbstractPrincipalCollection {
* @return INode
*/
public function getChildForPrincipal(array $principalInfo) {
- list(,$name) = \Sabre\Uri\split($principalInfo['uri']);
+ list(, $name) = \Sabre\Uri\split($principalInfo['uri']);
$user = \OC::$server->getUserSession()->getUser();
if (is_null($user) || $name !== $user->getUID()) {
throw new \Sabre\DAV\Exception\Forbidden();
}
- return new VersionHome($principalInfo, $this->rootFolder);
+ return new VersionHome($principalInfo, $this->rootFolder, $this->userManager, $this->versionManager);
}
public function getName() {
diff --git a/apps/files_versions/lib/Sabre/VersionCollection.php b/apps/files_versions/lib/Sabre/VersionCollection.php
index 481a5f491c3..9a3a6a365f0 100644
--- a/apps/files_versions/lib/Sabre/VersionCollection.php
+++ b/apps/files_versions/lib/Sabre/VersionCollection.php
@@ -21,11 +21,15 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OCA\Files_Versions\Sabre;
use OCA\Files_Versions\Storage;
+use OCA\Files_Versions\Versions\IVersion;
+use OCA\Files_Versions\Versions\IVersionManager;
use OCP\Files\File;
use OCP\Files\Folder;
+use OCP\IUser;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\ICollection;
@@ -37,13 +41,17 @@ class VersionCollection implements ICollection {
/** @var File */
private $file;
- /** @var string */
- private $userId;
+ /** @var IUser */
+ private $user;
+
+ /** @var IVersionManager */
+ private $versionManager;
- public function __construct(Folder $userFolder, File $file, string $userId) {
+ public function __construct(Folder $userFolder, File $file, IUser $user, IVersionManager $versionManager) {
$this->userFolder = $userFolder;
$this->file = $file;
- $this->userId = $userId;
+ $this->user = $user;
+ $this->versionManager = $versionManager;
}
public function createFile($name, $data = null) {
@@ -68,10 +76,10 @@ class VersionCollection implements ICollection {
}
public function getChildren(): array {
- $versions = Storage::getVersions($this->userId, $this->userFolder->getRelativePath($this->file->getPath()));
+ $versions = $this->versionManager->getVersionsForFile($this->user, $this->file);
- return array_map(function (array $data) {
- return new VersionFile($data, $this->userFolder->getParent());
+ return array_map(function (IVersion $version) {
+ return new VersionFile($version, $this->versionManager);
}, $versions);
}
diff --git a/apps/files_versions/lib/Sabre/VersionFile.php b/apps/files_versions/lib/Sabre/VersionFile.php
index 347058448fc..2d630008d2a 100644
--- a/apps/files_versions/lib/Sabre/VersionFile.php
+++ b/apps/files_versions/lib/Sabre/VersionFile.php
@@ -21,26 +21,26 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OCA\Files_Versions\Sabre;
-use OCA\Files_Versions\Storage;
-use OCP\Files\File;
-use OCP\Files\Folder;
+use OCA\Files_Versions\Versions\IVersion;
+use OCA\Files_Versions\Versions\IVersionManager;
use OCP\Files\NotFoundException;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\IFile;
class VersionFile implements IFile {
- /** @var array */
- private $data;
+ /** @var IVersion */
+ private $version;
- /** @var Folder */
- private $userRoot;
+ /** @var IVersionManager */
+ private $versionManager;
- public function __construct(array $data, Folder $userRoot) {
- $this->data = $data;
- $this->userRoot = $userRoot;
+ public function __construct(IVersion $version, IVersionManager $versionManager) {
+ $this->version = $version;
+ $this->versionManager = $versionManager;
}
public function put($data) {
@@ -49,27 +49,22 @@ class VersionFile implements IFile {
public function get() {
try {
- /** @var Folder $versions */
- $versions = $this->userRoot->get('files_versions');
- /** @var File $version */
- $version = $versions->get($this->data['path'].'.v'.$this->data['version']);
+ return $this->versionManager->read($this->version);
} catch (NotFoundException $e) {
throw new NotFound();
}
-
- return $version->fopen('rb');
}
public function getContentType(): string {
- return $this->data['mimetype'];
+ return $this->version->getMimeType();
}
public function getETag(): string {
- return $this->data['version'];
+ return (string)$this->version->getRevisionId();
}
public function getSize(): int {
- return $this->data['size'];
+ return $this->version->getSize();
}
public function delete() {
@@ -77,7 +72,7 @@ class VersionFile implements IFile {
}
public function getName(): string {
- return $this->data['version'];
+ return (string)$this->version->getRevisionId();
}
public function setName($name) {
@@ -85,10 +80,10 @@ class VersionFile implements IFile {
}
public function getLastModified(): int {
- return (int)$this->data['version'];
+ return $this->version->getTimestamp();
}
- public function rollBack(): bool {
- return Storage::rollback($this->data['path'], $this->data['version']);
+ public function rollBack() {
+ $this->versionManager->rollback($this->version);
}
}
diff --git a/apps/files_versions/lib/Sabre/VersionHome.php b/apps/files_versions/lib/Sabre/VersionHome.php
index 7a99d2376d4..7be5974bbbe 100644
--- a/apps/files_versions/lib/Sabre/VersionHome.php
+++ b/apps/files_versions/lib/Sabre/VersionHome.php
@@ -20,9 +20,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OCA\Files_Versions\Sabre;
+use OC\User\NoUserException;
+use OCA\Files_Versions\Versions\IVersionManager;
use OCP\Files\IRootFolder;
+use OCP\IUserManager;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\ICollection;
@@ -34,9 +38,25 @@ class VersionHome implements ICollection {
/** @var IRootFolder */
private $rootFolder;
- public function __construct(array $principalInfo, IRootFolder $rootFolder) {
+ /** @var IUserManager */
+ private $userManager;
+
+ /** @var IVersionManager */
+ private $versionManager;
+
+ public function __construct(array $principalInfo, IRootFolder $rootFolder, IUserManager $userManager, IVersionManager $versionManager) {
$this->principalInfo = $principalInfo;
$this->rootFolder = $rootFolder;
+ $this->userManager = $userManager;
+ $this->versionManager = $versionManager;
+ }
+
+ private function getUser() {
+ list(, $name) = \Sabre\Uri\split($this->principalInfo['uri']);
+ $user = $this->userManager->get($name);
+ if (!$user) {
+ throw new NoUserException();
+ }
}
public function delete() {
@@ -44,8 +64,7 @@ class VersionHome implements ICollection {
}
public function getName(): string {
- list(,$name) = \Sabre\Uri\split($this->principalInfo['uri']);
- return $name;
+ return $this->getUser()->getUID();
}
public function setName($name) {
@@ -61,22 +80,22 @@ class VersionHome implements ICollection {
}
public function getChild($name) {
- list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']);
+ $user = $this->getUser();
if ($name === 'versions') {
- return new VersionRoot($userId, $this->rootFolder);
+ return new VersionRoot($user, $this->rootFolder, $this->versionManager);
}
if ($name === 'restore') {
- return new RestoreFolder($userId);
+ return new RestoreFolder();
}
}
public function getChildren() {
- list(,$userId) = \Sabre\Uri\split($this->principalInfo['uri']);
+ $user = $this->getUser();
return [
- new VersionRoot($userId, $this->rootFolder),
- new RestoreFolder($userId),
+ new VersionRoot($user, $this->rootFolder, $this->versionManager),
+ new RestoreFolder(),
];
}
diff --git a/apps/files_versions/lib/Sabre/VersionRoot.php b/apps/files_versions/lib/Sabre/VersionRoot.php
index 743b1c6ef1b..1c689a4d87b 100644
--- a/apps/files_versions/lib/Sabre/VersionRoot.php
+++ b/apps/files_versions/lib/Sabre/VersionRoot.php
@@ -23,23 +23,29 @@ declare(strict_types=1);
*/
namespace OCA\Files_Versions\Sabre;
+use OCA\Files_Versions\Versions\IVersionManager;
use OCP\Files\File;
use OCP\Files\IRootFolder;
+use OCP\IUser;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\ICollection;
class VersionRoot implements ICollection {
- /** @var string */
- private $userId;
+ /** @var IUser */
+ private $user;
/** @var IRootFolder */
private $rootFolder;
- public function __construct(string $userId, IRootFolder $rootFolder) {
- $this->userId = $userId;
+ /** @var IVersionManager */
+ private $versionManager;
+
+ public function __construct(IUser $user, IRootFolder $rootFolder, IVersionManager $versionManager) {
+ $this->user = $user;
$this->rootFolder = $rootFolder;
+ $this->versionManager = $versionManager;
}
public function delete() {
@@ -63,7 +69,7 @@ class VersionRoot implements ICollection {
}
public function getChild($name) {
- $userFolder = $this->rootFolder->getUserFolder($this->userId);
+ $userFolder = $this->rootFolder->getUserFolder($this->user->getUID());
$fileId = (int)$name;
$nodes = $userFolder->getById($fileId);
@@ -78,7 +84,7 @@ class VersionRoot implements ICollection {
throw new NotFound();
}
- return new VersionCollection($userFolder, $node, $this->userId);
+ return new VersionCollection($userFolder, $node, $this->user, $this->versionManager);
}
public function getChildren(): array {
diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php
index 401544cc5d7..e2e4888cbce 100644
--- a/apps/files_versions/lib/Storage.php
+++ b/apps/files_versions/lib/Storage.php
@@ -48,6 +48,7 @@ use OC\Files\View;
use OCA\Files_Versions\AppInfo\Application;
use OCA\Files_Versions\Command\Expire;
use OCA\Files_Versions\Events\CreateVersionEvent;
+use OCA\Files_Versions\Versions\IVersionManager;
use OCP\Files\NotFoundException;
use OCP\Lock\ILockingProvider;
use OCP\User;
@@ -178,10 +179,10 @@ class Storage {
list($uid, $filename) = self::getUidAndFilename($filename);
$files_view = new View('/'.$uid .'/files');
- $users_view = new View('/'.$uid);
$eventDispatcher = \OC::$server->getEventDispatcher();
- $id = $files_view->getFileInfo($filename)->getId();
+ $fileInfo = $files_view->getFileInfo($filename);
+ $id = $fileInfo->getId();
$nodes = \OC::$server->getRootFolder()->getById($id);
foreach ($nodes as $node) {
$event = new CreateVersionEvent($node);
@@ -192,20 +193,16 @@ class Storage {
}
// no use making versions for empty files
- if ($files_view->filesize($filename) === 0) {
+ if ($fileInfo->getSize() === 0) {
return false;
}
- // create all parent folders
- self::createMissingDirectories($filename, $users_view);
-
- self::scheduleExpire($uid, $filename);
+ /** @var IVersionManager $versionManager */
+ $versionManager = \OC::$server->query(IVersionManager::class);
+ $userManager = \OC::$server->getUserManager();
+ $user = $userManager->get($uid);
- // store a new version of a file
- $mtime = $users_view->filemtime('files/' . $filename);
- $users_view->copy('files/' . $filename, 'files_versions/' . $filename . '.v' . $mtime);
- // call getFileInfo to enforce a file cache entry for the new version
- $users_view->getFileInfo('files_versions/' . $filename . '.v' . $mtime);
+ $versionManager->createVersion($user, $fileInfo);
}
@@ -695,7 +692,7 @@ class Storage {
* @param string $uid owner of the file
* @param string $fileName file/folder for which to schedule expiration
*/
- private static function scheduleExpire($uid, $fileName) {
+ public static function scheduleExpire($uid, $fileName) {
// let the admin disable auto expire
$expiration = self::getExpiration();
if ($expiration->isEnabled()) {
@@ -833,7 +830,7 @@ class Storage {
* "files" folder
* @param View $view view on data/user/
*/
- private static function createMissingDirectories($filename, $view) {
+ public static function createMissingDirectories($filename, $view) {
$dirname = Filesystem::normalizePath(dirname($filename));
$dirParts = explode('/', $dirname);
$dir = "/files_versions";
diff --git a/apps/files_versions/lib/Versions/BackendNotFoundException.php b/apps/files_versions/lib/Versions/BackendNotFoundException.php
new file mode 100644
index 00000000000..09985a716b9
--- /dev/null
+++ b/apps/files_versions/lib/Versions/BackendNotFoundException.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Versions\Versions;
+
+class BackendNotFoundException extends \Exception {
+
+}
diff --git a/apps/files_versions/lib/Versions/IVersion.php b/apps/files_versions/lib/Versions/IVersion.php
new file mode 100644
index 00000000000..b6fc95814d8
--- /dev/null
+++ b/apps/files_versions/lib/Versions/IVersion.php
@@ -0,0 +1,99 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Versions\Versions;
+
+use OCP\Files\FileInfo;
+use OCP\IUser;
+
+/**
+ * @since 15.0.0
+ */
+interface IVersion {
+ /**
+ * @return IVersionBackend
+ * @since 15.0.0
+ */
+ public function getBackend(): IVersionBackend;
+
+ /**
+ * Get the file info of the source file
+ *
+ * @return FileInfo
+ * @since 15.0.0
+ */
+ public function getSourceFile(): FileInfo;
+
+ /**
+ * Get the id of the revision for the file
+ *
+ * @return int
+ * @since 15.0.0
+ */
+ public function getRevisionId(): int;
+
+ /**
+ * Get the timestamp this version was created
+ *
+ * @return int
+ * @since 15.0.0
+ */
+ public function getTimestamp(): int;
+
+ /**
+ * Get the size of this version
+ *
+ * @return int
+ * @since 15.0.0
+ */
+ public function getSize(): int;
+
+ /**
+ * Get the name of the source file at the time of making this version
+ *
+ * @return string
+ * @since 15.0.0
+ */
+ public function getSourceFileName(): string;
+
+ /**
+ * Get the mimetype of this version
+ *
+ * @return string
+ * @since 15.0.0
+ */
+ public function getMimeType(): string;
+
+ /**
+ * Get the path of this version
+ *
+ * @return string
+ * @since 15.0.0
+ */
+ public function getVersionPath(): string;
+
+ /**
+ * @return IUser
+ * @since 15.0.0
+ */
+ public function getUser(): IUser;
+}
diff --git a/apps/files_versions/lib/Versions/IVersionBackend.php b/apps/files_versions/lib/Versions/IVersionBackend.php
new file mode 100644
index 00000000000..616d535f7fd
--- /dev/null
+++ b/apps/files_versions/lib/Versions/IVersionBackend.php
@@ -0,0 +1,81 @@
+<?php declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Versions\Versions;
+
+use OCP\Files\File;
+use OCP\Files\FileInfo;
+use OCP\Files\NotFoundException;
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\IUser;
+
+/**
+ * @since 15.0.0
+ */
+interface IVersionBackend {
+ /**
+ * Get all versions for a file
+ *
+ * @param IUser $user
+ * @param FileInfo $file
+ * @return IVersion[]
+ * @since 15.0.0
+ */
+ public function getVersionsForFile(IUser $user, FileInfo $file): array;
+
+ /**
+ * Create a new version for a file
+ *
+ * @param IUser $user
+ * @param FileInfo $file
+ * @since 15.0.0
+ */
+ public function createVersion(IUser $user, FileInfo $file);
+
+ /**
+ * Restore this version
+ *
+ * @param IVersion $version
+ * @since 15.0.0
+ */
+ public function rollback(IVersion $version);
+
+ /**
+ * Open the file for reading
+ *
+ * @param IVersion $version
+ * @return resource
+ * @throws NotFoundException
+ * @since 15.0.0
+ */
+ public function read(IVersion $version);
+
+ /**
+ * Get the preview for a specific version of a file
+ *
+ * @param IUser $user
+ * @param FileInfo $sourceFile
+ * @param int $revision
+ * @return ISimpleFile
+ * @since 15.0.0
+ */
+ public function getVersionFile(IUser $user, FileInfo $sourceFile, int $revision): File;
+}
diff --git a/apps/files_versions/lib/Versions/IVersionManager.php b/apps/files_versions/lib/Versions/IVersionManager.php
new file mode 100644
index 00000000000..748b649b1a2
--- /dev/null
+++ b/apps/files_versions/lib/Versions/IVersionManager.php
@@ -0,0 +1,36 @@
+<?php declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Versions\Versions;
+
+/**
+ * @since 15.0.0
+ */
+interface IVersionManager extends IVersionBackend {
+ /**
+ * Register a new backend
+ *
+ * @param string $storageType
+ * @param IVersionBackend $backend
+ * @since 15.0.0
+ */
+ public function registerBackend(string $storageType, IVersionBackend $backend);
+}
diff --git a/apps/files_versions/lib/Versions/LegacyVersionsBackend.php b/apps/files_versions/lib/Versions/LegacyVersionsBackend.php
new file mode 100644
index 00000000000..7293aca641e
--- /dev/null
+++ b/apps/files_versions/lib/Versions/LegacyVersionsBackend.php
@@ -0,0 +1,105 @@
+<?php declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Versions\Versions;
+
+use OC\Files\View;
+use OCA\Files_Versions\Storage;
+use OCP\Files\File;
+use OCP\Files\FileInfo;
+use OCP\Files\Folder;
+use OCP\Files\IRootFolder;
+use OCP\Files\NotFoundException;
+use OCP\IUser;
+
+class LegacyVersionsBackend implements IVersionBackend {
+ /** @var IRootFolder */
+ private $rootFolder;
+
+ public function __construct(IRootFolder $rootFolder) {
+ $this->rootFolder = $rootFolder;
+ }
+
+ public function getVersionsForFile(IUser $user, FileInfo $file): array {
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $versions = Storage::getVersions($user->getUID(), $userFolder->getRelativePath($file->getPath()));
+
+ return array_map(function (array $data) use ($file, $user) {
+ return new Version(
+ (int)$data['version'],
+ (int)$data['version'],
+ $data['name'],
+ (int)$data['size'],
+ $data['mimetype'],
+ $data['path'],
+ $file,
+ $this,
+ $user
+ );
+ }, $versions);
+ }
+
+ public function createVersion(IUser $user, FileInfo $file) {
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $relativePath = $userFolder->getRelativePath($file->getPath());
+ $userView = new View('/' . $user->getUID());
+ // create all parent folders
+ Storage::createMissingDirectories($relativePath, $userView);
+
+ Storage::scheduleExpire($user->getUID(), $relativePath);
+
+ // store a new version of a file
+ $userView->copy('files/' . $relativePath, 'files_versions/' . $relativePath . '.v' . $file->getMtime());
+ // ensure the file is scanned
+ $userView->getFileInfo('files_versions/' . $relativePath . '.v' . $file->getMtime());
+ }
+
+ public function rollback(IVersion $version) {
+ return Storage::rollback($version->getVersionPath(), $version->getRevisionId());
+ }
+
+ private function getVersionFolder(IUser $user): Folder {
+ $userRoot = $this->rootFolder->getUserFolder($user->getUID())
+ ->getParent();
+ try {
+ /** @var Folder $folder */
+ $folder = $userRoot->get('files_versions');
+ return $folder;
+ } catch (NotFoundException $e) {
+ return $userRoot->newFolder('files_versions');
+ }
+ }
+
+ public function read(IVersion $version) {
+ $versions = $this->getVersionFolder($version->getUser());
+ /** @var File $file */
+ $file = $versions->get($version->getVersionPath() . '.v' . $version->getRevisionId());
+ return $file->fopen('r');
+ }
+
+ public function getVersionFile(IUser $user, FileInfo $sourceFile, int $revision): File {
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $versionFolder = $this->getVersionFolder($user);
+ /** @var File $file */
+ $file = $versionFolder->get($userFolder->getRelativePath($sourceFile->getPath()) . '.v' . $revision);
+ return $file;
+ }
+}
diff --git a/apps/files_versions/lib/Versions/Version.php b/apps/files_versions/lib/Versions/Version.php
new file mode 100644
index 00000000000..5988234db61
--- /dev/null
+++ b/apps/files_versions/lib/Versions/Version.php
@@ -0,0 +1,113 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Versions\Versions;
+
+use OCP\Files\FileInfo;
+use OCP\IUser;
+
+class Version implements IVersion {
+ /** @var int */
+ private $timestamp;
+
+ /** @var int */
+ private $revisionId;
+
+ /** @var string */
+ private $name;
+
+ /** @var int */
+ private $size;
+
+ /** @var string */
+ private $mimetype;
+
+ /** @var string */
+ private $path;
+
+ /** @var FileInfo */
+ private $sourceFileInfo;
+
+ /** @var IVersionBackend */
+ private $backend;
+
+ /** @var IUser */
+ private $user;
+
+ public function __construct(
+ int $timestamp,
+ int $revisionId,
+ string $name,
+ int $size,
+ string $mimetype,
+ string $path,
+ FileInfo $sourceFileInfo,
+ IVersionBackend $backend,
+ IUser $user
+ ) {
+ $this->timestamp = $timestamp;
+ $this->revisionId = $revisionId;
+ $this->name = $name;
+ $this->size = $size;
+ $this->mimetype = $mimetype;
+ $this->path = $path;
+ $this->sourceFileInfo = $sourceFileInfo;
+ $this->backend = $backend;
+ $this->user = $user;
+ }
+
+ public function getBackend(): IVersionBackend {
+ return $this->backend;
+ }
+
+ public function getSourceFile(): FileInfo {
+ return $this->sourceFileInfo;
+ }
+
+ public function getRevisionId(): int {
+ return $this->revisionId;
+ }
+
+ public function getTimestamp(): int {
+ return $this->timestamp;
+ }
+
+ public function getSize(): int {
+ return $this->size;
+ }
+
+ public function getSourceFileName(): string {
+ return $this->name;
+ }
+
+ public function getMimeType(): string {
+ return $this->mimetype;
+ }
+
+ public function getVersionPath(): string {
+ return $this->path;
+ }
+
+ public function getUser(): IUser {
+ return $this->user;
+ }
+}
diff --git a/apps/files_versions/lib/Versions/VersionManager.php b/apps/files_versions/lib/Versions/VersionManager.php
new file mode 100644
index 00000000000..757b6002710
--- /dev/null
+++ b/apps/files_versions/lib/Versions/VersionManager.php
@@ -0,0 +1,93 @@
+<?php declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Versions\Versions;
+
+use OCP\Files\File;
+use OCP\Files\FileInfo;
+use OCP\Files\Storage\IStorage;
+use OCP\IUser;
+
+class VersionManager implements IVersionManager {
+ /** @var IVersionBackend[] */
+ private $backends = [];
+
+ public function registerBackend(string $storageType, IVersionBackend $backend) {
+ $this->backends[$storageType] = $backend;
+ }
+
+ /**
+ * @return IVersionBackend[]
+ */
+ private function getBackends(): array {
+ return $this->backends;
+ }
+
+ /**
+ * @param IStorage $storage
+ * @return IVersionBackend
+ * @throws BackendNotFoundException
+ */
+ public function getBackendForStorage(IStorage $storage): IVersionBackend {
+ $fullType = get_class($storage);
+ $backends = $this->getBackends();
+ $foundType = array_reduce(array_keys($backends), function ($type, $registeredType) use ($storage) {
+ if (
+ $storage->instanceOfStorage($registeredType) &&
+ ($type === '' || is_subclass_of($registeredType, $type))
+ ) {
+ return $registeredType;
+ } else {
+ return $type;
+ }
+ }, '');
+ if ($foundType === '') {
+ throw new BackendNotFoundException("Version backend for $fullType not found");
+ } else {
+ return $backends[$foundType];
+ }
+ }
+
+ public function getVersionsForFile(IUser $user, FileInfo $file): array {
+ $backend = $this->getBackendForStorage($file->getStorage());
+ return $backend->getVersionsForFile($user, $file);
+ }
+
+ public function createVersion(IUser $user, FileInfo $file) {
+ $backend = $this->getBackendForStorage($file->getStorage());
+ $backend->createVersion($user, $file);
+ }
+
+ public function rollback(IVersion $version) {
+ $backend = $version->getBackend();
+ return $backend->rollback($version);
+ }
+
+ public function read(IVersion $version) {
+ $backend = $version->getBackend();
+ return $backend->read($version);
+ }
+
+ public function getVersionFile(IUser $user, FileInfo $sourceFile, int $revision): File {
+ $backend = $this->getBackendForStorage($sourceFile->getStorage());
+ return $backend->getVersionFile($user, $sourceFile, $revision);
+ }
+}
diff --git a/apps/files_versions/tests/Controller/PreviewControllerTest.php b/apps/files_versions/tests/Controller/PreviewControllerTest.php
index 384f43cf495..7c248b36349 100644
--- a/apps/files_versions/tests/Controller/PreviewControllerTest.php
+++ b/apps/files_versions/tests/Controller/PreviewControllerTest.php
@@ -20,9 +20,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OCA\Files_Versions\Tests\Controller;
+use OC\User\User;
use OCA\Files_Versions\Controller\PreviewController;
+use OCA\Files_Versions\Versions\IVersionManager;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\FileDisplayResponse;
@@ -34,6 +37,8 @@ use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\IPreview;
use OCP\IRequest;
+use OCP\IUser;
+use OCP\IUserSession;
use Test\TestCase;
class PreviewControllerTest extends TestCase {
@@ -50,23 +55,39 @@ class PreviewControllerTest extends TestCase {
/** @var IPreview|\PHPUnit_Framework_MockObject_MockObject */
private $previewManager;
- /** @var PreviewController */
+ /** @var PreviewController|\PHPUnit_Framework_MockObject_MockObject */
private $controller;
+ /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
+ private $userSession;
+
+ /** @var IVersionManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $versionManager;
+
public function setUp() {
parent::setUp();
$this->rootFolder = $this->createMock(IRootFolder::class);
$this->userId = 'user';
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->any())
+ ->method('getUID')
+ ->willReturn($this->userId);
$this->mimeTypeDetector = $this->createMock(IMimeTypeDetector::class);
$this->previewManager = $this->createMock(IPreview::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->userSession->expects($this->any())
+ ->method('getUser')
+ ->willReturn($user);
+ $this->versionManager = $this->createMock(IVersionManager::class);
$this->controller = new PreviewController(
'files_versions',
$this->createMock(IRequest::class),
$this->rootFolder,
- $this->userId,
+ $this->userSession,
$this->mimeTypeDetector,
+ $this->versionManager,
$this->previewManager
);
}
@@ -102,24 +123,23 @@ class PreviewControllerTest extends TestCase {
public function testValidPreview() {
$userFolder = $this->createMock(Folder::class);
$userRoot = $this->createMock(Folder::class);
- $versions = $this->createMock(Folder::class);
$this->rootFolder->method('getUserFolder')
->with($this->userId)
->willReturn($userFolder);
$userFolder->method('getParent')
->willReturn($userRoot);
- $userRoot->method('get')
- ->with('files_versions')
- ->willReturn($versions);
- $this->mimeTypeDetector->method('detectPath')
- ->with($this->equalTo('file'))
- ->willReturn('myMime');
+ $sourceFile = $this->createMock(File::class);
+ $userFolder->method('get')
+ ->with('file')
+ ->willReturn($sourceFile);
$file = $this->createMock(File::class);
- $versions->method('get')
- ->with($this->equalTo('file.v42'))
+ $file->method('getMimetype')
+ ->willReturn('myMime');
+
+ $this->versionManager->method('getVersionFile')
->willReturn($file);
$preview = $this->createMock(ISimpleFile::class);
@@ -138,24 +158,23 @@ class PreviewControllerTest extends TestCase {
public function testVersionNotFound() {
$userFolder = $this->createMock(Folder::class);
$userRoot = $this->createMock(Folder::class);
- $versions = $this->createMock(Folder::class);
$this->rootFolder->method('getUserFolder')
->with($this->userId)
->willReturn($userFolder);
$userFolder->method('getParent')
->willReturn($userRoot);
- $userRoot->method('get')
- ->with('files_versions')
- ->willReturn($versions);
+
+ $sourceFile = $this->createMock(File::class);
+ $userFolder->method('get')
+ ->with('file')
+ ->willReturn($sourceFile);
$this->mimeTypeDetector->method('detectPath')
->with($this->equalTo('file'))
->willReturn('myMime');
- $file = $this->createMock(File::class);
- $versions->method('get')
- ->with($this->equalTo('file.v42'))
+ $this->versionManager->method('getVersionFile')
->willThrowException(new NotFoundException());
$res = $this->controller->getPreview('file', 10, 10, '42');
diff --git a/apps/oauth2/lib/Controller/OauthApiController.php b/apps/oauth2/lib/Controller/OauthApiController.php
index 2083741fa0c..73fed3654d5 100644
--- a/apps/oauth2/lib/Controller/OauthApiController.php
+++ b/apps/oauth2/lib/Controller/OauthApiController.php
@@ -22,8 +22,9 @@
namespace OCA\OAuth2\Controller;
use OC\Authentication\Exceptions\InvalidTokenException;
-use OC\Authentication\Token\ExpiredTokenException;
+use OC\Authentication\Exceptions\ExpiredTokenException;
use OC\Authentication\Token\IProvider as TokenProvider;
+use OC\Security\Bruteforce\Throttler;
use OCA\OAuth2\Db\AccessTokenMapper;
use OCA\OAuth2\Db\ClientMapper;
use OCA\OAuth2\Exceptions\AccessTokenNotFoundException;
@@ -49,6 +50,8 @@ class OauthApiController extends Controller {
private $secureRandom;
/** @var ITimeFactory */
private $time;
+ /** @var Throttler */
+ private $throttler;
/**
* @param string $appName
@@ -59,6 +62,7 @@ class OauthApiController extends Controller {
* @param TokenProvider $tokenProvider
* @param ISecureRandom $secureRandom
* @param ITimeFactory $time
+ * @param Throttler $throttler
*/
public function __construct($appName,
IRequest $request,
@@ -67,7 +71,8 @@ class OauthApiController extends Controller {
ClientMapper $clientMapper,
TokenProvider $tokenProvider,
ISecureRandom $secureRandom,
- ITimeFactory $time) {
+ ITimeFactory $time,
+ Throttler $throttler) {
parent::__construct($appName, $request);
$this->crypto = $crypto;
$this->accessTokenMapper = $accessTokenMapper;
@@ -75,6 +80,7 @@ class OauthApiController extends Controller {
$this->tokenProvider = $tokenProvider;
$this->secureRandom = $secureRandom;
$this->time = $time;
+ $this->throttler = $throttler;
}
/**
@@ -164,6 +170,8 @@ class OauthApiController extends Controller {
$accessToken->setEncryptedToken($this->crypto->encrypt($newToken, $newCode));
$this->accessTokenMapper->update($accessToken);
+ $this->throttler->resetDelay($this->request->getRemoteAddress(), 'login', ['user' => $appToken->getUID()]);
+
return new JSONResponse(
[
'access_token' => $newToken,
diff --git a/apps/oauth2/tests/Controller/OauthApiControllerTest.php b/apps/oauth2/tests/Controller/OauthApiControllerTest.php
index 10748485971..f5a8138fa2d 100644
--- a/apps/oauth2/tests/Controller/OauthApiControllerTest.php
+++ b/apps/oauth2/tests/Controller/OauthApiControllerTest.php
@@ -22,11 +22,10 @@
namespace OCA\OAuth2\Tests\Controller;
use OC\Authentication\Exceptions\InvalidTokenException;
+use OC\Authentication\Exceptions\ExpiredTokenException;
use OC\Authentication\Token\DefaultToken;
-use OC\Authentication\Token\DefaultTokenMapper;
-use OC\Authentication\Token\ExpiredTokenException;
use OC\Authentication\Token\IProvider as TokenProvider;
-use OC\Authentication\Token\IToken;
+use OC\Security\Bruteforce\Throttler;
use OCA\OAuth2\Controller\OauthApiController;
use OCA\OAuth2\Db\AccessToken;
use OCA\OAuth2\Db\AccessTokenMapper;
@@ -57,6 +56,8 @@ class OauthApiControllerTest extends TestCase {
private $secureRandom;
/** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */
private $time;
+ /** @var Throttler|\PHPUnit_Framework_MockObject_MockObject */
+ private $throttler;
/** @var OauthApiController */
private $oauthApiController;
@@ -70,6 +71,7 @@ class OauthApiControllerTest extends TestCase {
$this->tokenProvider = $this->createMock(TokenProvider::class);
$this->secureRandom = $this->createMock(ISecureRandom::class);
$this->time = $this->createMock(ITimeFactory::class);
+ $this->throttler = $this->createMock(Throttler::class);
$this->oauthApiController = new OauthApiController(
'oauth2',
@@ -79,7 +81,8 @@ class OauthApiControllerTest extends TestCase {
$this->clientMapper,
$this->tokenProvider,
$this->secureRandom,
- $this->time
+ $this->time,
+ $this->throttler
);
}
@@ -286,6 +289,17 @@ class OauthApiControllerTest extends TestCase {
'user_id' => 'userId',
]);
+ $this->request->method('getRemoteAddress')
+ ->willReturn('1.2.3.4');
+
+ $this->throttler->expects($this->once())
+ ->method('resetDelay')
+ ->with(
+ '1.2.3.4',
+ 'login',
+ ['user' => 'userId']
+ );
+
$this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', 'clientId', 'clientSecret'));
}
@@ -370,6 +384,17 @@ class OauthApiControllerTest extends TestCase {
$this->request->server['PHP_AUTH_USER'] = 'clientId';
$this->request->server['PHP_AUTH_PW'] = 'clientSecret';
+ $this->request->method('getRemoteAddress')
+ ->willReturn('1.2.3.4');
+
+ $this->throttler->expects($this->once())
+ ->method('resetDelay')
+ ->with(
+ '1.2.3.4',
+ 'login',
+ ['user' => 'userId']
+ );
+
$this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', null, null));
}
@@ -451,6 +476,17 @@ class OauthApiControllerTest extends TestCase {
'user_id' => 'userId',
]);
+ $this->request->method('getRemoteAddress')
+ ->willReturn('1.2.3.4');
+
+ $this->throttler->expects($this->once())
+ ->method('resetDelay')
+ ->with(
+ '1.2.3.4',
+ 'login',
+ ['user' => 'userId']
+ );
+
$this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', 'clientId', 'clientSecret'));
}
}
diff --git a/apps/sharebymail/tests/CapabilitiesTest.php b/apps/sharebymail/tests/CapabilitiesTest.php
new file mode 100644
index 00000000000..b1545994199
--- /dev/null
+++ b/apps/sharebymail/tests/CapabilitiesTest.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\ShareByMail\Tests;
+
+use OCA\ShareByMail\Capabilities;
+use Test\TestCase;
+
+class CapabilitiesTest extends TestCase {
+ /** @var Capabilities */
+ private $capabilities;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->capabilities = new Capabilities();
+ }
+
+ public function testGetCapabilities() {
+ $capabilities = [
+ 'files_sharing' =>
+ [
+ 'sharebymail' =>
+ [
+ 'enabled' => true,
+ 'upload_files_drop' => ['enabled' => true],
+ 'password' => ['enabled' => true],
+ 'expire_date' => ['enabled' => true]
+ ]
+ ]
+ ];
+
+ $this->assertSame($capabilities, $this->capabilities->getCapabilities());
+ }
+}
diff --git a/apps/systemtags/tests/Activity/SettingTest.php b/apps/systemtags/tests/Activity/SettingTest.php
new file mode 100644
index 00000000000..40fcea750a6
--- /dev/null
+++ b/apps/systemtags/tests/Activity/SettingTest.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\SystemTags\Tests\Activity;
+
+use OCA\SystemTags\Activity\Setting;
+use OCP\IL10N;
+use Test\TestCase;
+
+class SettingTest extends TestCase {
+ /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
+ private $l;
+ /** @var Setting */
+ private $setting;
+
+ public function setUp() {
+ parent::setUp();
+ $this->l = $this->createMock(IL10N::class);
+
+ $this->setting = new Setting($this->l);
+ }
+
+ public function testGetIdentifier() {
+ $this->assertSame('systemtags', $this->setting->getIdentifier());
+ }
+
+ public function testGetName() {
+ $this->l
+ ->expects($this->once())
+ ->method('t')
+ ->with('<strong>System tags</strong> for a file have been modified')
+ ->willReturn('<strong>System tags</strong> for a file have been modified');
+
+ $this->assertSame('<strong>System tags</strong> for a file have been modified', $this->setting->getName());
+ }
+
+ public function testGetPriority() {
+ $this->assertSame(50, $this->setting->getPriority());
+ }
+
+ public function testCanChangeStream() {
+ $this->assertSame(true, $this->setting->canChangeStream());
+ }
+
+ public function testIsDefaultEnabledStream() {
+ $this->assertSame(true, $this->setting->isDefaultEnabledStream());
+ }
+
+ public function testCanChangeMail() {
+ $this->assertSame(true, $this->setting->canChangeMail());
+ }
+
+ public function testIsDefaultEnabledMail() {
+ $this->assertSame(false, $this->setting->isDefaultEnabledMail());
+ }
+}
diff --git a/apps/user_ldap/composer/composer/autoload_classmap.php b/apps/user_ldap/composer/composer/autoload_classmap.php
index 98a1bbfa1b7..e25b7ee3126 100644
--- a/apps/user_ldap/composer/composer/autoload_classmap.php
+++ b/apps/user_ldap/composer/composer/autoload_classmap.php
@@ -56,7 +56,6 @@ return array(
'OCA\\User_LDAP\\Settings\\Section' => $baseDir . '/../lib/Settings/Section.php',
'OCA\\User_LDAP\\UserPluginManager' => $baseDir . '/../lib/UserPluginManager.php',
'OCA\\User_LDAP\\User\\DeletedUsersIndex' => $baseDir . '/../lib/User/DeletedUsersIndex.php',
- 'OCA\\User_LDAP\\User\\IUserTools' => $baseDir . '/../lib/User/IUserTools.php',
'OCA\\User_LDAP\\User\\Manager' => $baseDir . '/../lib/User/Manager.php',
'OCA\\User_LDAP\\User\\OfflineUser' => $baseDir . '/../lib/User/OfflineUser.php',
'OCA\\User_LDAP\\User\\User' => $baseDir . '/../lib/User/User.php',
diff --git a/apps/user_ldap/composer/composer/autoload_static.php b/apps/user_ldap/composer/composer/autoload_static.php
index 83e49daf0f3..23819055be4 100644
--- a/apps/user_ldap/composer/composer/autoload_static.php
+++ b/apps/user_ldap/composer/composer/autoload_static.php
@@ -71,7 +71,6 @@ class ComposerStaticInitUser_LDAP
'OCA\\User_LDAP\\Settings\\Section' => __DIR__ . '/..' . '/../lib/Settings/Section.php',
'OCA\\User_LDAP\\UserPluginManager' => __DIR__ . '/..' . '/../lib/UserPluginManager.php',
'OCA\\User_LDAP\\User\\DeletedUsersIndex' => __DIR__ . '/..' . '/../lib/User/DeletedUsersIndex.php',
- 'OCA\\User_LDAP\\User\\IUserTools' => __DIR__ . '/..' . '/../lib/User/IUserTools.php',
'OCA\\User_LDAP\\User\\Manager' => __DIR__ . '/..' . '/../lib/User/Manager.php',
'OCA\\User_LDAP\\User\\OfflineUser' => __DIR__ . '/..' . '/../lib/User/OfflineUser.php',
'OCA\\User_LDAP\\User\\User' => __DIR__ . '/..' . '/../lib/User/User.php',
diff --git a/apps/user_ldap/lib/Access.php b/apps/user_ldap/lib/Access.php
index d0d51ae8c85..fb2582e8266 100644
--- a/apps/user_ldap/lib/Access.php
+++ b/apps/user_ldap/lib/Access.php
@@ -46,7 +46,6 @@ namespace OCA\User_LDAP;
use OC\HintException;
use OC\Hooks\PublicEmitter;
use OCA\User_LDAP\Exceptions\ConstraintViolationException;
-use OCA\User_LDAP\User\IUserTools;
use OCA\User_LDAP\User\Manager;
use OCA\User_LDAP\User\OfflineUser;
use OCA\User_LDAP\Mapping\AbstractMapping;
@@ -59,7 +58,7 @@ use OCP\IUserManager;
* Class Access
* @package OCA\User_LDAP
*/
-class Access extends LDAPUtility implements IUserTools {
+class Access extends LDAPUtility {
const UUID_ATTRIBUTES = ['entryuuid', 'nsuniqueid', 'objectguid', 'guid', 'ipauniqueid'];
/** @var \OCA\User_LDAP\Connection */
diff --git a/apps/user_ldap/lib/User/IUserTools.php b/apps/user_ldap/lib/User/IUserTools.php
deleted file mode 100644
index 4ba9cebb1a6..00000000000
--- a/apps/user_ldap/lib/User/IUserTools.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-namespace OCA\User_LDAP\User;
-
-/**
- * IUserTools
- *
- * defines methods that are required by User class for LDAP interaction
- */
-interface IUserTools {
- public function getConnection();
-
- public function readAttribute($dn, $attr, $filter = 'objectClass=*');
-
- public function stringResemblesDN($string);
-
- public function dn2username($dn, $ldapname = null);
-
- public function username2dn($name);
-}
diff --git a/apps/user_ldap/lib/User/Manager.php b/apps/user_ldap/lib/User/Manager.php
index 9f2f3649777..13555f9e31b 100644
--- a/apps/user_ldap/lib/User/Manager.php
+++ b/apps/user_ldap/lib/User/Manager.php
@@ -45,7 +45,7 @@ use OCP\Notification\IManager as INotificationManager;
* cache
*/
class Manager {
- /** @var IUserTools */
+ /** @var Access */
protected $access;
/** @var IConfig */
@@ -110,11 +110,11 @@ class Manager {
}
/**
- * @brief binds manager to an instance of IUserTools (implemented by
- * Access). It needs to be assigned first before the manager can be used.
- * @param IUserTools
+ * Binds manager to an instance of Access.
+ * It needs to be assigned first before the manager can be used.
+ * @param Access
*/
- public function setLdapAccess(IUserTools $access) {
+ public function setLdapAccess(Access $access) {
$this->access = $access;
}
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 02764a72eca..706424d3189 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -30,6 +30,7 @@
namespace OCA\User_LDAP\User;
+use OCA\User_LDAP\Access;
use OCA\User_LDAP\Connection;
use OCA\User_LDAP\FilesystemHelper;
use OCA\User_LDAP\LogWrapper;
@@ -48,7 +49,7 @@ use OCP\Notification\IManager as INotificationManager;
*/
class User {
/**
- * @var IUserTools
+ * @var Access
*/
protected $access;
/**
@@ -110,8 +111,7 @@ class User {
* @brief constructor, make sure the subclasses call this one!
* @param string $username the internal username
* @param string $dn the LDAP DN
- * @param IUserTools $access an instance that implements IUserTools for
- * LDAP interaction
+ * @param Access $access
* @param IConfig $config
* @param FilesystemHelper $fs
* @param Image $image any empty instance
@@ -120,7 +120,7 @@ class User {
* @param IUserManager $userManager
* @param INotificationManager $notificationManager
*/
- public function __construct($username, $dn, IUserTools $access,
+ public function __construct($username, $dn, Access $access,
IConfig $config, FilesystemHelper $fs, Image $image,
LogWrapper $log, IAvatarManager $avatarManager, IUserManager $userManager,
INotificationManager $notificationManager) {
@@ -414,14 +414,23 @@ class User {
*
* @param string $displayName
* @param string $displayName2
- * @returns string the effective display name
+ * @return string the effective display name
*/
public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
$displayName2 = (string)$displayName2;
if($displayName2 !== '') {
$displayName .= ' (' . $displayName2 . ')';
}
- $this->store('displayName', $displayName);
+ $oldName = $this->config->getUserValue($this->uid, 'user_ldap', 'displayName', null);
+ if ($oldName !== $displayName) {
+ $this->store('displayName', $displayName);
+ $user = $this->userManager->get($this->getUsername());
+ if (!empty($oldName) && $user instanceof \OC\User\User) {
+ // if it was empty, it would be a new record, not a change emitting the trigger could
+ // potentially cause a UniqueConstraintViolationException, depending on some factors.
+ $user->triggerChange('displayName', $displayName);
+ }
+ }
return $displayName;
}
diff --git a/apps/user_ldap/tests/User/ManagerTest.php b/apps/user_ldap/tests/User/ManagerTest.php
index 104a70ff700..5c111abdc4e 100644
--- a/apps/user_ldap/tests/User/ManagerTest.php
+++ b/apps/user_ldap/tests/User/ManagerTest.php
@@ -28,11 +28,13 @@
namespace OCA\User_LDAP\Tests\User;
+use OCA\User_LDAP\Access;
+use OCA\User_LDAP\Connection;
use OCA\User_LDAP\FilesystemHelper;
use OCA\User_LDAP\ILDAPWrapper;
use OCA\User_LDAP\LogWrapper;
-use OCA\User_LDAP\User\IUserTools;
use OCA\User_LDAP\User\Manager;
+use OCA\User_LDAP\User\User;
use OCP\IAvatarManager;
use OCP\IConfig;
use OCP\IDBConnection;
@@ -48,200 +50,181 @@ use OCP\Notification\IManager as INotificationManager;
* @package OCA\User_LDAP\Tests\User
*/
class ManagerTest extends \Test\TestCase {
+ /** @var Access|\PHPUnit_Framework_MockObject_MockObject */
+ protected $access;
- private function getTestInstances() {
- $access = $this->createMock(IUserTools::class);
- $config = $this->createMock(IConfig::class);
- $filesys = $this->createMock(FilesystemHelper::class);
- $log = $this->createMock(LogWrapper::class);
- $avaMgr = $this->createMock(IAvatarManager::class);
- $image = $this->createMock(Image::class);
- $dbc = $this->createMock(IDBConnection::class);
- $userMgr = $this->createMock(IUserManager::class);
- $notiMgr = $this->createMock(INotificationManager::class);
-
- $connection = new \OCA\User_LDAP\Connection(
- $lw = $this->createMock(ILDAPWrapper::class),
- '',
- null
- );
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
- $access->expects($this->any())
- ->method('getConnection')
- ->will($this->returnValue($connection));
+ /** @var FilesystemHelper|\PHPUnit_Framework_MockObject_MockObject */
+ protected $fileSystemHelper;
- return array($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr);
- }
+ /** @var LogWrapper|\PHPUnit_Framework_MockObject_MockObject */
+ protected $log;
- public function testGetByDNExisting() {
- list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) =
- $this->getTestInstances();
+ /** @var IAvatarManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $avatarManager;
- $inputDN = 'cn=foo,dc=foobar,dc=bar';
- $uid = '563418fc-423b-1033-8d1c-ad5f418ee02e';
+ /** @var Image|\PHPUnit_Framework_MockObject_MockObject */
+ protected $image;
- $access->expects($this->once())
- ->method('stringResemblesDN')
- ->with($this->equalTo($inputDN))
- ->will($this->returnValue(true));
+ /** @var IDBConnection|\PHPUnit_Framework_MockObject_MockObject */
+ protected $dbc;
- $access->expects($this->once())
- ->method('dn2username')
- ->with($this->equalTo($inputDN))
- ->will($this->returnValue($uid));
+ /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $ncUserManager;
- $access->expects($this->never())
- ->method('username2dn');
+ /** @var INotificationManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $notificationManager;
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr);
- $manager->setLdapAccess($access);
- $user = $manager->get($inputDN);
+ /** @var ILDAPWrapper|\PHPUnit_Framework_MockObject_MockObject */
+ protected $ldapWrapper;
- // Now we fetch the user again. If this leads to a failing test,
- // runtime caching the manager is broken.
- $user = $manager->get($inputDN);
-
- $this->assertInstanceOf('\OCA\User_LDAP\User\User', $user);
- }
+ /** @var Connection */
+ protected $connection;
- public function testGetByEDirectoryDN() {
- list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) =
- $this->getTestInstances();
+ /** @var Manager */
+ protected $manager;
- $inputDN = 'uid=foo,o=foobar,c=bar';
- $uid = '563418fc-423b-1033-8d1c-ad5f418ee02e';
+ public function setUp() {
+ parent::setUp();
- $access->expects($this->once())
- ->method('stringResemblesDN')
- ->with($this->equalTo($inputDN))
- ->will($this->returnValue(true));
-
- $access->expects($this->once())
- ->method('dn2username')
- ->with($this->equalTo($inputDN))
- ->will($this->returnValue($uid));
+ $this->access = $this->createMock(Access::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->fileSystemHelper = $this->createMock(FilesystemHelper::class);
+ $this->log = $this->createMock(LogWrapper::class);
+ $this->avatarManager = $this->createMock(IAvatarManager::class);
+ $this->image = $this->createMock(Image::class);
+ $this->dbc = $this->createMock(IDBConnection::class);
+ $this->ncUserManager = $this->createMock(IUserManager::class);
+ $this->notificationManager = $this->createMock(INotificationManager::class);
- $access->expects($this->never())
- ->method('username2dn');
+ $this->ldapWrapper = $this->createMock(ILDAPWrapper::class);
+ $this->connection = new Connection($this->ldapWrapper, '', null);
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr);
- $manager->setLdapAccess($access);
- $user = $manager->get($inputDN);
+ $this->access->expects($this->any())
+ ->method('getConnection')
+ ->will($this->returnValue($this->connection));
+
+ /** @noinspection PhpUnhandledExceptionInspection */
+ $this->manager = new Manager(
+ $this->config,
+ $this->fileSystemHelper,
+ $this->log,
+ $this->avatarManager,
+ $this->image,
+ $this->dbc,
+ $this->ncUserManager,
+ $this->notificationManager
+ );
- $this->assertInstanceOf('\OCA\User_LDAP\User\User', $user);
+ $this->manager->setLdapAccess($this->access);
}
- public function testGetByExoticDN() {
- list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) =
- $this->getTestInstances();
+ public function dnProvider() {
+ return [
+ ['cn=foo,dc=foobar,dc=bar'],
+ ['uid=foo,o=foobar,c=bar'],
+ ['ab=cde,f=ghei,mno=pq'],
+ ];
+ }
- $inputDN = 'ab=cde,f=ghei,mno=pq';
+ /**
+ * @dataProvider dnProvider
+ */
+ public function testGetByDNExisting(string $inputDN) {
$uid = '563418fc-423b-1033-8d1c-ad5f418ee02e';
- $access->expects($this->once())
+ $this->access->expects($this->once())
->method('stringResemblesDN')
->with($this->equalTo($inputDN))
->will($this->returnValue(true));
-
- $access->expects($this->once())
+ $this->access->expects($this->once())
->method('dn2username')
->with($this->equalTo($inputDN))
->will($this->returnValue($uid));
-
- $access->expects($this->never())
+ $this->access->expects($this->never())
->method('username2dn');
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr);
- $manager->setLdapAccess($access);
- $user = $manager->get($inputDN);
+ /** @noinspection PhpUnhandledExceptionInspection */
+ $this->manager->get($inputDN);
- $this->assertInstanceOf('\OCA\User_LDAP\User\User', $user);
+ // Now we fetch the user again. If this leads to a failing test,
+ // runtime caching the manager is broken.
+ /** @noinspection PhpUnhandledExceptionInspection */
+ $user = $this->manager->get($inputDN);
+
+ $this->assertInstanceOf(User::class, $user);
}
public function testGetByDNNotExisting() {
- list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) =
- $this->getTestInstances();
-
$inputDN = 'cn=gone,dc=foobar,dc=bar';
- $access->expects($this->once())
+ $this->access->expects($this->once())
->method('stringResemblesDN')
->with($this->equalTo($inputDN))
->will($this->returnValue(true));
-
- $access->expects($this->once())
+ $this->access->expects($this->once())
->method('dn2username')
->with($this->equalTo($inputDN))
->will($this->returnValue(false));
-
- $access->expects($this->once())
+ $this->access->expects($this->once())
->method('username2dn')
->with($this->equalTo($inputDN))
->will($this->returnValue(false));
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr);
- $manager->setLdapAccess($access);
- $user = $manager->get($inputDN);
+ /** @noinspection PhpUnhandledExceptionInspection */
+ $user = $this->manager->get($inputDN);
$this->assertNull($user);
}
public function testGetByUidExisting() {
- list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) =
- $this->getTestInstances();
-
$dn = 'cn=foo,dc=foobar,dc=bar';
$uid = '563418fc-423b-1033-8d1c-ad5f418ee02e';
- $access->expects($this->never())
+ $this->access->expects($this->never())
->method('dn2username');
-
- $access->expects($this->once())
+ $this->access->expects($this->once())
->method('username2dn')
->with($this->equalTo($uid))
->will($this->returnValue($dn));
-
- $access->expects($this->once())
+ $this->access->expects($this->once())
->method('stringResemblesDN')
->with($this->equalTo($uid))
->will($this->returnValue(false));
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr);
- $manager->setLdapAccess($access);
- $user = $manager->get($uid);
+ /** @noinspection PhpUnhandledExceptionInspection */
+ $this->manager->get($uid);
// Now we fetch the user again. If this leads to a failing test,
// runtime caching the manager is broken.
- $user = $manager->get($uid);
+ /** @noinspection PhpUnhandledExceptionInspection */
+ $user = $this->manager->get($uid);
- $this->assertInstanceOf('\OCA\User_LDAP\User\User', $user);
+ $this->assertInstanceOf(User::class, $user);
}
public function testGetByUidNotExisting() {
- list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) =
- $this->getTestInstances();
-
$uid = 'gone';
- $access->expects($this->never())
+ $this->access->expects($this->never())
->method('dn2username');
-
- $access->expects($this->exactly(1))
+ $this->access->expects($this->exactly(1))
->method('username2dn')
->with($this->equalTo($uid))
->will($this->returnValue(false));
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr);
- $manager->setLdapAccess($access);
- $user = $manager->get($uid);
+ /** @noinspection PhpUnhandledExceptionInspection */
+ $user = $this->manager->get($uid);
$this->assertNull($user);
}
public function attributeRequestProvider() {
return [
- [ false ],
- [ true ],
+ [false],
+ [true],
];
}
@@ -249,23 +232,16 @@ class ManagerTest extends \Test\TestCase {
* @dataProvider attributeRequestProvider
*/
public function testGetAttributes($minimal) {
- list($access, $config, $filesys, $image, $log, $avaMgr, $dbc, $userMgr, $notiMgr) =
- $this->getTestInstances();
-
- $manager = new Manager($config, $filesys, $log, $avaMgr, $image, $dbc, $userMgr, $notiMgr);
- $manager->setLdapAccess($access);
-
- $connection = $access->getConnection();
- $connection->setConfiguration([
+ $this->connection->setConfiguration([
'ldapEmailAttribute' => 'mail',
'ldapUserAvatarRule' => 'default',
'ldapQuotaAttribute' => '',
]);
- $attributes = $manager->getAttributes($minimal);
+ $attributes = $this->manager->getAttributes($minimal);
$this->assertTrue(in_array('dn', $attributes));
- $this->assertTrue(in_array($access->getConnection()->ldapEmailAttribute, $attributes));
+ $this->assertTrue(in_array($this->access->getConnection()->ldapEmailAttribute, $attributes));
$this->assertFalse(in_array('', $attributes));
$this->assertSame(!$minimal, in_array('jpegphoto', $attributes));
$this->assertSame(!$minimal, in_array('thumbnailphoto', $attributes));
diff --git a/apps/user_ldap/tests/User/UserTest.php b/apps/user_ldap/tests/User/UserTest.php
index 837c72a3a31..6ff9defe47b 100644
--- a/apps/user_ldap/tests/User/UserTest.php
+++ b/apps/user_ldap/tests/User/UserTest.php
@@ -998,23 +998,58 @@ class UserTest extends \Test\TestCase {
public function displayNameProvider() {
return [
- ['Roland Deschain', '', 'Roland Deschain'],
- ['Roland Deschain', null, 'Roland Deschain'],
- ['Roland Deschain', 'gunslinger@darktower.com', 'Roland Deschain (gunslinger@darktower.com)'],
+ ['Roland Deschain', '', 'Roland Deschain', false],
+ ['Roland Deschain', '', 'Roland Deschain', true],
+ ['Roland Deschain', null, 'Roland Deschain', false],
+ ['Roland Deschain', 'gunslinger@darktower.com', 'Roland Deschain (gunslinger@darktower.com)', false],
+ ['Roland Deschain', 'gunslinger@darktower.com', 'Roland Deschain (gunslinger@darktower.com)', true],
];
}
/**
* @dataProvider displayNameProvider
*/
- public function testComposeAndStoreDisplayName($part1, $part2, $expected) {
+ public function testComposeAndStoreDisplayName($part1, $part2, $expected, $expectTriggerChange) {
$this->config->expects($this->once())
->method('setUserValue');
+ $oldName = $expectTriggerChange ? 'xxGunslingerxx' : null;
+ $this->config->expects($this->once())
+ ->method('getUserValue')
+ ->with($this->user->getUsername(), 'user_ldap', 'displayName', null)
+ ->willReturn($oldName);
+
+ $ncUserObj = $this->createMock(\OC\User\User::class);
+ if ($expectTriggerChange) {
+ $ncUserObj->expects($this->once())
+ ->method('triggerChange')
+ ->with('displayName', $expected);
+ } else {
+ $ncUserObj->expects($this->never())
+ ->method('triggerChange');
+ }
+ $this->userManager->expects($this->once())
+ ->method('get')
+ ->willReturn($ncUserObj);
$displayName = $this->user->composeAndStoreDisplayName($part1, $part2);
$this->assertSame($expected, $displayName);
}
+ public function testComposeAndStoreDisplayNameNoOverwrite() {
+ $displayName = 'Randall Flagg';
+ $this->config->expects($this->never())
+ ->method('setUserValue');
+ $this->config->expects($this->once())
+ ->method('getUserValue')
+ ->willReturn($displayName);
+
+ $this->userManager->expects($this->never())
+ ->method('get'); // Implicit: no triggerChange can be called
+
+ $composedDisplayName = $this->user->composeAndStoreDisplayName($displayName);
+ $this->assertSame($composedDisplayName, $displayName);
+ }
+
public function testHandlePasswordExpiryWarningDefaultPolicy() {
$this->connection->expects($this->any())
->method('__get')