aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/phpunit-32bits.yml4
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php49
-rw-r--r--apps/files_sharing/src/share.js2
-rw-r--r--apps/provisioning_api/lib/Controller/UsersController.php8
-rw-r--r--apps/provisioning_api/tests/Controller/UsersControllerTest.php157
-rw-r--r--apps/settings/l10n/fi.js1
-rw-r--r--apps/settings/l10n/fi.json1
-rw-r--r--apps/settings/l10n/ru.js2
-rw-r--r--apps/settings/l10n/ru.json2
-rw-r--r--apps/user_ldap/lib/Access.php5
-rw-r--r--apps/user_ldap/lib/AccessFactory.php7
-rw-r--r--apps/user_ldap/lib/Group_LDAP.php15
-rw-r--r--apps/user_ldap/lib/Group_Proxy.php6
-rw-r--r--apps/user_ldap/lib/Jobs/Sync.php19
-rw-r--r--apps/user_ldap/tests/Jobs/SyncTest.php3
-rw-r--r--build/integration/features/provisioning-v1.feature44
-rw-r--r--core/Command/User/ListCommand.php2
-rw-r--r--dist/files_sharing-additionalScripts.js4
-rw-r--r--dist/files_sharing-additionalScripts.js.map2
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/private/Comments/Manager.php3
-rw-r--r--lib/private/Files/Filesystem.php2
-rw-r--r--lib/private/Files/Node/File.php12
-rw-r--r--lib/private/Files/Storage/Wrapper/Encoding.php2
-rw-r--r--lib/private/Files/Storage/Wrapper/Encryption.php2
-rw-r--r--lib/private/Files/Storage/Wrapper/Jail.php2
-rw-r--r--lib/private/Files/Storage/Wrapper/Wrapper.php2
-rw-r--r--lib/private/Files/View.php2
-rw-r--r--lib/private/Group/Backend.php2
-rw-r--r--lib/private/Group/Database.php37
-rw-r--r--lib/private/Group/Group.php45
-rw-r--r--lib/private/User/LazyUser.php18
-rw-r--r--lib/private/User/Manager.php27
-rw-r--r--lib/public/Files/File.php1
-rw-r--r--lib/public/Files/Storage.php2
-rw-r--r--lib/public/Files/Storage/IStorage.php2
-rw-r--r--lib/public/Group/Backend/ISearchableGroupBackend.php51
-rw-r--r--lib/public/GroupInterface.php6
-rw-r--r--lib/public/IGroup.php2
-rw-r--r--tests/lib/Comments/ManagerTest.php30
-rw-r--r--tests/lib/Group/GroupTest.php34
-rw-r--r--tests/lib/Group/ManagerTest.php61
-rw-r--r--tests/lib/Template/JSResourceLocatorTest.php9
-rw-r--r--tests/lib/Util/Group/Dummy.php46
45 files changed, 501 insertions, 234 deletions
diff --git a/.github/workflows/phpunit-32bits.yml b/.github/workflows/phpunit-32bits.yml
index 100c95bd210..ef81b2226e6 100644
--- a/.github/workflows/phpunit-32bits.yml
+++ b/.github/workflows/phpunit-32bits.yml
@@ -1,6 +1,10 @@
name: PHPUnit 32bits
on:
+ pull_request:
+ paths:
+ - 'version.php'
+ - '.github/workflows/phpunit-32bits.yml'
workflow_dispatch:
schedule:
- cron: "15 1 * * 1-6"
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index e1595a98ea3..3287d9447d8 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -627,16 +627,6 @@ class ShareAPIController extends OCSController {
$share->setSendPasswordByTalk(true);
}
-
- //Expire date
- if ($expireDate !== '') {
- try {
- $expireDate = $this->parseDate($expireDate);
- $share->setExpirationDate($expireDate);
- } catch (\Exception $e) {
- throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
- }
- }
} elseif ($shareType === IShare::TYPE_REMOTE) {
if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$node->getPath(), $shareType]));
@@ -710,6 +700,16 @@ class ShareAPIController extends OCSController {
throw new OCSBadRequestException($this->l->t('Unknown share type'));
}
+ //Expire date
+ if ($expireDate !== '') {
+ try {
+ $expireDate = $this->parseDate($expireDate);
+ $share->setExpirationDate($expireDate);
+ } catch (\Exception $e) {
+ throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
+ }
+ }
+
$share->setShareType($shareType);
if ($note !== '') {
@@ -1216,17 +1216,6 @@ class ShareAPIController extends OCSController {
$permissions = $newPermissions;
}
- if ($expireDate === '') {
- $share->setExpirationDate(null);
- } elseif ($expireDate !== null) {
- try {
- $expireDate = $this->parseDate($expireDate);
- } catch (\Exception $e) {
- throw new OCSBadRequestException($e->getMessage(), $e);
- }
- $share->setExpirationDate($expireDate);
- }
-
if ($password === '') {
$share->setPassword(null);
} elseif ($password !== null) {
@@ -1256,17 +1245,17 @@ class ShareAPIController extends OCSController {
if ($permissions !== null) {
$share->setPermissions($permissions);
}
+ }
- if ($expireDate === '') {
- $share->setExpirationDate(null);
- } elseif ($expireDate !== null) {
- try {
- $expireDate = $this->parseDate($expireDate);
- } catch (\Exception $e) {
- throw new OCSBadRequestException($e->getMessage(), $e);
- }
- $share->setExpirationDate($expireDate);
+ if ($expireDate === '') {
+ $share->setExpirationDate(null);
+ } elseif ($expireDate !== null) {
+ try {
+ $expireDate = $this->parseDate($expireDate);
+ } catch (\Exception $e) {
+ throw new OCSBadRequestException($e->getMessage(), $e);
}
+ $share->setExpirationDate($expireDate);
}
try {
diff --git a/apps/files_sharing/src/share.js b/apps/files_sharing/src/share.js
index 06eea5807a1..a54f2f13698 100644
--- a/apps/files_sharing/src/share.js
+++ b/apps/files_sharing/src/share.js
@@ -94,7 +94,7 @@ import { getCapabilities } from '@nextcloud/capabilities'
}
if (_.isFunction(fileData.canDownload) && !fileData.canDownload()) {
delete fileActions.actions.all.Download
- if (fileData.permissions & OC.PERMISSION_UPDATE === 0) {
+ if ((fileData.permissions & OC.PERMISSION_UPDATE) === 0) {
// neither move nor copy is allowed, remove the action completely
delete fileActions.actions.all.MoveCopy
}
diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php
index bc97e32faa4..b005acc4d7f 100644
--- a/apps/provisioning_api/lib/Controller/UsersController.php
+++ b/apps/provisioning_api/lib/Controller/UsersController.php
@@ -942,11 +942,11 @@ class UsersController extends AUserData {
if (filter_var($value, FILTER_VALIDATE_EMAIL) && $value !== $targetUser->getSystemEMailAddress()) {
$userAccount = $this->accountManager->getAccount($targetUser);
$mailCollection = $userAccount->getPropertyCollection(IAccountManager::COLLECTION_EMAIL);
- foreach ($mailCollection->getProperties() as $property) {
- if ($property->getValue() === $value) {
- break;
- }
+
+ if ($mailCollection->getPropertyByValue($value)) {
+ throw new OCSException('', 102);
}
+
$mailCollection->addPropertyWithDefaults($value);
$this->accountManager->updateAccount($userAccount);
} else {
diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php
index b8b8fa8715c..419f9eceb79 100644
--- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php
+++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php
@@ -52,7 +52,9 @@ use OCA\Settings\Mailer\NewUserMailHelper;
use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
use OCP\Accounts\IAccountProperty;
+use OCP\Accounts\IAccountPropertyCollection;
use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\OCS\OCSException;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
use OCP\IGroup;
@@ -1544,7 +1546,162 @@ class UsersControllerTest extends TestCase {
$this->assertEquals([], $this->api->editUser('UserToEdit', 'email', 'demo@nextcloud.com')->getData());
}
+ public function testEditUserRegularUserSelfEditAddAdditionalEmailValid(): void {
+ $loggedInUser = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $loggedInUser
+ ->expects($this->any())
+ ->method('getUID')
+ ->willReturn('UID');
+ $targetUser = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->willReturn($loggedInUser);
+ $this->userManager
+ ->expects($this->once())
+ ->method('get')
+ ->with('UserToEdit')
+ ->willReturn($targetUser);
+ $targetUser
+ ->expects($this->any())
+ ->method('getUID')
+ ->willReturn('UID');
+
+ $backend = $this->createMock(UserInterface::class);
+ $targetUser
+ ->expects($this->any())
+ ->method('getBackend')
+ ->willReturn($backend);
+
+ $userAccount = $this->createMock(IAccount::class);
+
+ $this->accountManager
+ ->expects($this->once())
+ ->method('getAccount')
+ ->with($targetUser)
+ ->willReturn($userAccount);
+ $this->accountManager
+ ->expects($this->once())
+ ->method('updateAccount')
+ ->with($userAccount);
+
+ $this->assertEquals([], $this->api->editUser('UserToEdit', 'additional_mail', 'demo1@nextcloud.com')->getData());
+ }
+
+ public function testEditUserRegularUserSelfEditAddAdditionalEmailMainAddress(): void {
+ $loggedInUser = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $loggedInUser
+ ->expects($this->any())
+ ->method('getUID')
+ ->willReturn('UID');
+ $targetUser = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->willReturn($loggedInUser);
+ $this->userManager
+ ->expects($this->once())
+ ->method('get')
+ ->with('UserToEdit')
+ ->willReturn($targetUser);
+ $targetUser
+ ->expects($this->any())
+ ->method('getUID')
+ ->willReturn('UID');
+
+ $backend = $this->createMock(UserInterface::class);
+ $targetUser
+ ->expects($this->any())
+ ->method('getBackend')
+ ->willReturn($backend);
+ $targetUser
+ ->expects($this->any())
+ ->method('getSystemEMailAddress')
+ ->willReturn('demo@nextcloud.com');
+
+ $userAccount = $this->createMock(IAccount::class);
+ $this->accountManager
+ ->expects($this->never())
+ ->method('getAccount')
+ ->with($targetUser)
+ ->willReturn($userAccount);
+ $this->accountManager
+ ->expects($this->never())
+ ->method('updateAccount')
+ ->with($userAccount);
+
+ $this->expectException(OCSException::class);
+ $this->expectExceptionCode(102);
+ $this->api->editUser('UserToEdit', 'additional_mail', 'demo@nextcloud.com')->getData();
+ }
+
+ public function testEditUserRegularUserSelfEditAddAdditionalEmailDuplicate(): void {
+ $loggedInUser = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $loggedInUser
+ ->expects($this->any())
+ ->method('getUID')
+ ->willReturn('UID');
+ $targetUser = $this->getMockBuilder(IUser::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->willReturn($loggedInUser);
+ $this->userManager
+ ->expects($this->once())
+ ->method('get')
+ ->with('UserToEdit')
+ ->willReturn($targetUser);
+ $targetUser
+ ->expects($this->any())
+ ->method('getUID')
+ ->willReturn('UID');
+
+ $backend = $this->createMock(UserInterface::class);
+ $targetUser
+ ->expects($this->any())
+ ->method('getBackend')
+ ->willReturn($backend);
+
+ $property = $this->createMock(IAccountProperty::class);
+ $property->method('getValue')
+ ->willReturn('demo1@nextcloud.com');
+ $collection = $this->createMock(IAccountPropertyCollection::class);
+ $collection->method('getPropertyByValue')
+ ->with('demo1@nextcloud.com')
+ ->willReturn($property);
+
+ $userAccount = $this->createMock(IAccount::class);
+ $userAccount->method('getPropertyCollection')
+ ->with(IAccountManager::COLLECTION_EMAIL)
+ ->willReturn($collection);
+
+ $this->accountManager
+ ->expects($this->once())
+ ->method('getAccount')
+ ->with($targetUser)
+ ->willReturn($userAccount);
+ $this->accountManager
+ ->expects($this->never())
+ ->method('updateAccount')
+ ->with($userAccount);
+
+ $this->expectException(OCSException::class);
+ $this->expectExceptionCode(102);
+ $this->api->editUser('UserToEdit', 'additional_mail', 'demo1@nextcloud.com')->getData();
+ }
public function testEditUserRegularUserSelfEditChangeEmailInvalid() {
$this->expectException(\OCP\AppFramework\OCS\OCSException::class);
diff --git a/apps/settings/l10n/fi.js b/apps/settings/l10n/fi.js
index ec224881578..b252cdff030 100644
--- a/apps/settings/l10n/fi.js
+++ b/apps/settings/l10n/fi.js
@@ -237,6 +237,7 @@ OC.L10N.register(
"Upload profile picture" : "Lähetä profiilikuva",
"Choose profile picture from Files" : "Valitse profiilikuva tiedostoista",
"Remove profile picture" : "Poista profiilikuva",
+ "The file must be a PNG or JPG" : "Tiedoston tulee olla PNG tai JPG",
"Picture provided by original account" : "Kuvan tarjoaa alkuperäinen tili",
"Cancel" : "Peru",
"Set as profile picture" : "Aseta profiilikuvaksi",
diff --git a/apps/settings/l10n/fi.json b/apps/settings/l10n/fi.json
index 3cbe0e7fd2f..49150fde99f 100644
--- a/apps/settings/l10n/fi.json
+++ b/apps/settings/l10n/fi.json
@@ -235,6 +235,7 @@
"Upload profile picture" : "Lähetä profiilikuva",
"Choose profile picture from Files" : "Valitse profiilikuva tiedostoista",
"Remove profile picture" : "Poista profiilikuva",
+ "The file must be a PNG or JPG" : "Tiedoston tulee olla PNG tai JPG",
"Picture provided by original account" : "Kuvan tarjoaa alkuperäinen tili",
"Cancel" : "Peru",
"Set as profile picture" : "Aseta profiilikuvaksi",
diff --git a/apps/settings/l10n/ru.js b/apps/settings/l10n/ru.js
index 90cd711f410..805ffc1c42a 100644
--- a/apps/settings/l10n/ru.js
+++ b/apps/settings/l10n/ru.js
@@ -425,7 +425,7 @@ OC.L10N.register(
"App bundles" : "Пакеты приложений",
"Featured apps" : "Рекомендуемые приложения",
"Show to everyone" : "Видим для всех",
- "Show to logged in users only" : "Видим только для пользователей, вошедших в систему",
+ "Show to logged in users only" : "Видим только для вошедших в систему",
"Hide" : "Скрыт",
"Download and enable" : "Скачать и включить",
"Enable untested app" : "Включить непроверенное приложение",
diff --git a/apps/settings/l10n/ru.json b/apps/settings/l10n/ru.json
index 4575793ac0f..63f94cf89d2 100644
--- a/apps/settings/l10n/ru.json
+++ b/apps/settings/l10n/ru.json
@@ -423,7 +423,7 @@
"App bundles" : "Пакеты приложений",
"Featured apps" : "Рекомендуемые приложения",
"Show to everyone" : "Видим для всех",
- "Show to logged in users only" : "Видим только для пользователей, вошедших в систему",
+ "Show to logged in users only" : "Видим только для вошедших в систему",
"Hide" : "Скрыт",
"Download and enable" : "Скачать и включить",
"Enable untested app" : "Включить непроверенное приложение",
diff --git a/apps/user_ldap/lib/Access.php b/apps/user_ldap/lib/Access.php
index 9a97a28c376..3f120caefe6 100644
--- a/apps/user_ldap/lib/Access.php
+++ b/apps/user_ldap/lib/Access.php
@@ -631,7 +631,7 @@ class Access extends LDAPUtility {
* gives back the user names as they are used ownClod internally
*
* @param array $ldapUsers as returned by fetchList()
- * @return array an array with the user names to use in Nextcloud
+ * @return array<int,string> an array with the user names to use in Nextcloud
*
* gives back the user names as they are used ownClod internally
* @throws \Exception
@@ -644,7 +644,7 @@ class Access extends LDAPUtility {
* gives back the group names as they are used ownClod internally
*
* @param array $ldapGroups as returned by fetchList()
- * @return array an array with the group names to use in Nextcloud
+ * @return array<int,string> an array with the group names to use in Nextcloud
*
* gives back the group names as they are used ownClod internally
* @throws \Exception
@@ -655,6 +655,7 @@ class Access extends LDAPUtility {
/**
* @param array[] $ldapObjects as returned by fetchList()
+ * @return array<int,string>
* @throws \Exception
*/
private function ldap2NextcloudNames(array $ldapObjects, bool $isUsers): array {
diff --git a/apps/user_ldap/lib/AccessFactory.php b/apps/user_ldap/lib/AccessFactory.php
index f0820f1444f..693f7e8ba12 100644
--- a/apps/user_ldap/lib/AccessFactory.php
+++ b/apps/user_ldap/lib/AccessFactory.php
@@ -26,11 +26,11 @@ namespace OCA\User_LDAP;
use OCA\User_LDAP\User\Manager;
use OCP\IConfig;
use OCP\IUserManager;
+use OCP\Server;
use Psr\Log\LoggerInterface;
class AccessFactory {
private ILDAPWrapper $ldap;
- private Manager $userManager;
private Helper $helper;
private IConfig $config;
private IUserManager $ncUserManager;
@@ -38,13 +38,11 @@ class AccessFactory {
public function __construct(
ILDAPWrapper $ldap,
- Manager $userManager,
Helper $helper,
IConfig $config,
IUserManager $ncUserManager,
LoggerInterface $logger) {
$this->ldap = $ldap;
- $this->userManager = $userManager;
$this->helper = $helper;
$this->config = $config;
$this->ncUserManager = $ncUserManager;
@@ -52,10 +50,11 @@ class AccessFactory {
}
public function get(Connection $connection): Access {
+ /* Each Access instance gets its own Manager instance, see OCA\User_LDAP\AppInfo\Application::register() */
return new Access(
$connection,
$this->ldap,
- $this->userManager,
+ Server::get(Manager::class),
$this->helper,
$this->config,
$this->ncUserManager,
diff --git a/apps/user_ldap/lib/Group_LDAP.php b/apps/user_ldap/lib/Group_LDAP.php
index b32e031175f..84267171d37 100644
--- a/apps/user_ldap/lib/Group_LDAP.php
+++ b/apps/user_ldap/lib/Group_LDAP.php
@@ -45,11 +45,11 @@
namespace OCA\User_LDAP;
use Exception;
+use OC\ServerNotAvailableException;
use OCP\Cache\CappedMemoryCache;
use OCP\GroupInterface;
use OCP\Group\Backend\IDeleteGroupBackend;
use OCP\Group\Backend\IGetDisplayNameBackend;
-use OC\ServerNotAvailableException;
use Psr\Log\LoggerInterface;
class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, IGetDisplayNameBackend, IDeleteGroupBackend {
@@ -466,7 +466,7 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
}
/**
- * @return array A list of users that have the given group as gid number
+ * @return array<int,string> A list of users that have the given group as gid number
* @throws ServerNotAvailableException
*/
public function getUsersInGidNumber(
@@ -591,6 +591,7 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
/**
* @throws ServerNotAvailableException
+ * @return array<int,string>
*/
public function getUsersInPrimaryGroup(
string $groupDN,
@@ -840,7 +841,7 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
* @param string $search
* @param int $limit
* @param int $offset
- * @return array with user ids
+ * @return array<int,string> user ids
* @throws Exception
* @throws ServerNotAvailableException
*/
@@ -909,7 +910,11 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
if (empty($ldap_users)) {
break;
}
- $groupUsers[] = $this->access->dn2username($ldap_users[0]['dn'][0]);
+ $uid = $this->access->dn2username($ldap_users[0]['dn'][0]);
+ if (!$uid) {
+ break;
+ }
+ $groupUsers[] = $uid;
break;
default:
//we got DNs, check if we need to filter by search or we can give back all of them
@@ -1163,7 +1168,7 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
* Returns the supported actions as int to be
* compared with GroupInterface::CREATE_GROUP etc.
*/
- public function implementsActions($actions) {
+ public function implementsActions($actions): bool {
return (bool)((GroupInterface::COUNT_USERS |
GroupInterface::DELETE_GROUP |
$this->groupPluginManager->getImplementedActions()) & $actions);
diff --git a/apps/user_ldap/lib/Group_Proxy.php b/apps/user_ldap/lib/Group_Proxy.php
index c8c986318ec..5f8d0562fd9 100644
--- a/apps/user_ldap/lib/Group_Proxy.php
+++ b/apps/user_ldap/lib/Group_Proxy.php
@@ -171,7 +171,7 @@ class Group_Proxy extends Proxy implements \OCP\GroupInterface, IGroupLDAP, IGet
/**
* get a list of all users in a group
*
- * @return string[] with user ids
+ * @return array<int,string> user ids
*/
public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
$this->setup();
@@ -334,4 +334,8 @@ class Group_Proxy extends Proxy implements \OCP\GroupInterface, IGroupLDAP, IGet
public function getBackendName(): string {
return 'LDAP';
}
+
+ public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array {
+ return $this->handleRequest($gid, 'searchInGroup', [$gid, $search, $limit, $offset]);
+ }
}
diff --git a/apps/user_ldap/lib/Jobs/Sync.php b/apps/user_ldap/lib/Jobs/Sync.php
index 1ba24af5399..f8a9b14d02f 100644
--- a/apps/user_ldap/lib/Jobs/Sync.php
+++ b/apps/user_ldap/lib/Jobs/Sync.php
@@ -31,7 +31,6 @@ use OCA\User_LDAP\ConnectionFactory;
use OCA\User_LDAP\Helper;
use OCA\User_LDAP\LDAP;
use OCA\User_LDAP\Mapping\UserMapping;
-use OCA\User_LDAP\User\Manager;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\TimedJob;
use OCP\IAvatarManager;
@@ -48,8 +47,6 @@ class Sync extends TimedJob {
protected $ldapHelper;
/** @var LDAP */
protected $ldap;
- /** @var Manager */
- protected $userManager;
/** @var UserMapping */
protected $mapper;
/** @var IConfig */
@@ -69,9 +66,8 @@ class Sync extends TimedJob {
/** @var AccessFactory */
protected $accessFactory;
- public function __construct(Manager $userManager, ITimeFactory $time) {
+ public function __construct(ITimeFactory $time) {
parent::__construct($time);
- $this->userManager = $userManager;
$this->setInterval(
(int)\OC::$server->getConfig()->getAppValue(
'user_ldap',
@@ -350,10 +346,6 @@ class Sync extends TimedJob {
$this->notificationManager = \OC::$server->getNotificationManager();
}
- if (isset($argument['userManager'])) {
- $this->userManager = $argument['userManager'];
- }
-
if (isset($argument['mapper'])) {
$this->mapper = $argument['mapper'];
} else {
@@ -369,14 +361,7 @@ class Sync extends TimedJob {
if (isset($argument['accessFactory'])) {
$this->accessFactory = $argument['accessFactory'];
} else {
- $this->accessFactory = new AccessFactory(
- $this->ldap,
- $this->userManager,
- $this->ldapHelper,
- $this->config,
- $this->ncUserManager,
- $this->logger
- );
+ $this->accessFactory = \OCP\Server::get(AccessFactory::class);
}
}
}
diff --git a/apps/user_ldap/tests/Jobs/SyncTest.php b/apps/user_ldap/tests/Jobs/SyncTest.php
index 8d23efb4da8..3d9fc54e631 100644
--- a/apps/user_ldap/tests/Jobs/SyncTest.php
+++ b/apps/user_ldap/tests/Jobs/SyncTest.php
@@ -43,7 +43,6 @@ use OCP\Notification\IManager;
use Test\TestCase;
class SyncTest extends TestCase {
-
/** @var array */
protected $arguments;
/** @var Helper|\PHPUnit\Framework\MockObject\MockObject */
@@ -99,7 +98,7 @@ class SyncTest extends TestCase {
'accessFactory' => $this->accessFactory,
];
- $this->sync = new Sync($this->userManager, $this->createMock(ITimeFactory::class));
+ $this->sync = new Sync($this->createMock(ITimeFactory::class));
}
public function intervalDataProvider() {
diff --git a/build/integration/features/provisioning-v1.feature b/build/integration/features/provisioning-v1.feature
index d34e1bceb6a..5ba6b7f63dd 100644
--- a/build/integration/features/provisioning-v1.feature
+++ b/build/integration/features/provisioning-v1.feature
@@ -199,6 +199,28 @@ Feature: provisioning
| value | private |
Then the OCS status code should be "100"
And the HTTP status code should be "200"
+ And sending "PUT" to "/cloud/users/brand-new-user" with
+ | key | email |
+ | value | no-reply@nextcloud.com |
+ And the OCS status code should be "100"
+ And the HTTP status code should be "200"
+ # Duplicating primary address
+ And sending "PUT" to "/cloud/users/brand-new-user" with
+ | key | additional_mail |
+ | value | no-reply@nextcloud.com |
+ And the OCS status code should be "102"
+ And the HTTP status code should be "200"
+ And sending "PUT" to "/cloud/users/brand-new-user" with
+ | key | additional_mail |
+ | value | no.reply2@nextcloud.com |
+ And the OCS status code should be "100"
+ And the HTTP status code should be "200"
+ # Duplicating another additional address
+ And sending "PUT" to "/cloud/users/brand-new-user" with
+ | key | additional_mail |
+ | value | no.reply2@nextcloud.com |
+ And the OCS status code should be "102"
+ And the HTTP status code should be "200"
Then user "brand-new-user" has
| id | brand-new-user |
| phoneScope | v2-private |
@@ -214,21 +236,21 @@ Feature: provisioning
And As an "brand-new-user"
When sending "PUT" to "/cloud/users/brand-new-user" with
| key | additional_mail |
- | value | no.reply@nextcloud.com |
+ | value | no.reply3@nextcloud.com |
And the OCS status code should be "100"
And the HTTP status code should be "200"
And sending "PUT" to "/cloud/users/brand-new-user" with
| key | additional_mail |
- | value | noreply@nextcloud.com |
+ | value | noreply4@nextcloud.com |
And the OCS status code should be "100"
And the HTTP status code should be "200"
When sending "PUT" to "/cloud/users/brand-new-user/additional_mailScope" with
- | key | no.reply@nextcloud.com |
+ | key | no.reply3@nextcloud.com |
| value | v2-federated |
Then the OCS status code should be "100"
And the HTTP status code should be "200"
When sending "PUT" to "/cloud/users/brand-new-user/additional_mailScope" with
- | key | noreply@nextcloud.com |
+ | key | noreply4@nextcloud.com |
| value | v2-published |
Then the OCS status code should be "100"
And the HTTP status code should be "200"
@@ -260,11 +282,11 @@ Feature: provisioning
And As an "brand-new-user"
When sending "PUT" to "/cloud/users/brand-new-user" with
| key | additional_mail |
- | value | no.reply@nextcloud.com |
+ | value | no.reply5@nextcloud.com |
And the OCS status code should be "100"
And the HTTP status code should be "200"
When sending "PUT" to "/cloud/users/brand-new-user/additional_mailScope" with
- | key | no.reply@nextcloud.com |
+ | key | no.reply5@nextcloud.com |
| value | invalid |
Then the OCS status code should be "102"
And the HTTP status code should be "200"
@@ -274,23 +296,23 @@ Feature: provisioning
And As an "brand-new-user"
When sending "PUT" to "/cloud/users/brand-new-user" with
| key | additional_mail |
- | value | no.reply@nextcloud.com |
+ | value | no.reply6@nextcloud.com |
And the OCS status code should be "100"
And the HTTP status code should be "200"
And sending "PUT" to "/cloud/users/brand-new-user" with
| key | additional_mail |
- | value | noreply@nextcloud.com |
+ | value | noreply7@nextcloud.com |
And the OCS status code should be "100"
And the HTTP status code should be "200"
When sending "PUT" to "/cloud/users/brand-new-user/additional_mail" with
- | key | no.reply@nextcloud.com |
+ | key | no.reply6@nextcloud.com |
| value | |
And the OCS status code should be "100"
And the HTTP status code should be "200"
Then user "brand-new-user" has
- | additional_mail | noreply@nextcloud.com |
+ | additional_mail | noreply7@nextcloud.com |
Then user "brand-new-user" has not
- | additional_mail | no.reply@nextcloud.com |
+ | additional_mail | no.reply6@nextcloud.com |
Scenario: An admin cannot edit user account property scopes
Given As an "admin"
diff --git a/core/Command/User/ListCommand.php b/core/Command/User/ListCommand.php
index c254a8a11cf..bf4bf7f030e 100644
--- a/core/Command/User/ListCommand.php
+++ b/core/Command/User/ListCommand.php
@@ -74,7 +74,7 @@ class ListCommand extends Base {
}
protected function execute(InputInterface $input, OutputInterface $output): int {
- $users = $this->userManager->search('', (int) $input->getOption('limit'), (int) $input->getOption('offset'));
+ $users = $this->userManager->searchDisplayName('', (int) $input->getOption('limit'), (int) $input->getOption('offset'));
$this->writeArrayInOutputFormat($input, $output, $this->formatUsers($users, (bool)$input->getOption('info')));
return 0;
diff --git a/dist/files_sharing-additionalScripts.js b/dist/files_sharing-additionalScripts.js
index 01be3f4fc9e..afe18e1628f 100644
--- a/dist/files_sharing-additionalScripts.js
+++ b/dist/files_sharing-additionalScripts.js
@@ -1,3 +1,3 @@
/*! For license information please see files_sharing-additionalScripts.js.LICENSE.txt */
-(()=>{var e,a={5972:(e,a,r)=>{"use strict";var i=r(95573),n=r.n(i),s=r(41922),o=r(42515);_.extend(OC.Files.Client,{PROPERTY_SHARE_TYPES:"{"+OC.Files.Client.NS_OWNCLOUD+"}share-types",PROPERTY_OWNER_ID:"{"+OC.Files.Client.NS_OWNCLOUD+"}owner-id",PROPERTY_OWNER_DISPLAY_NAME:"{"+OC.Files.Client.NS_OWNCLOUD+"}owner-display-name"}),OCA.Sharing||(OCA.Sharing={}),OCA.Sharing.Util={_REMOTE_OWNER_REGEXP:new RegExp("^(([^@]*)@(([^@^/\\s]*)@)?)((https://)?[^[\\s/]*)([/](.*))?$"),attach:function(e){var a;if(null!==(a=(0,o.getCapabilities)().files_sharing)&&void 0!==a&&a.api_enabled&&"trashbin"!==e.id&&"files.public"!==e.id){var r=e.fileActions,i=e._createRow;e._createRow=function(e){var a=i.apply(this,arguments),t=OCA.Sharing.Util.getSharePermissions(e);return 0===e.permissions&&(delete r.actions.all.Comment,delete r.actions.all.Details,delete r.actions.all.Goto),_.isFunction(e.canDownload)&&!e.canDownload()&&(delete r.actions.all.Download,e.permissions&0===OC.PERMISSION_UPDATE&&delete r.actions.all.MoveCopy),a.attr("data-share-permissions",t),a.attr("data-share-attributes",JSON.stringify(e.shareAttributes)),e.shareOwner&&(a.attr("data-share-owner",e.shareOwner),a.attr("data-share-owner-id",e.shareOwnerId),"shared-root"===e.mountType&&a.attr("data-permissions",e.permissions|OC.PERMISSION_UPDATE)),e.recipientData&&!_.isEmpty(e.recipientData)&&a.attr("data-share-recipient-data",JSON.stringify(e.recipientData)),e.shareTypes&&a.attr("data-share-types",e.shareTypes.join(",")),a};var n=e.elementToFile;e.elementToFile=function(e){var a=n.apply(this,arguments);if(a.shareAttributes=JSON.parse(e.attr("data-share-attributes")||"[]"),a.sharePermissions=e.attr("data-share-permissions")||void 0,a.shareOwner=e.attr("data-share-owner")||void 0,a.shareOwnerId=e.attr("data-share-owner-id")||void 0,e.attr("data-share-types")&&(a.shareTypes=e.attr("data-share-types").split(",")),e.attr("data-expiration")){var r=parseInt(e.attr("data-expiration"));a.shares=[],a.shares.push({expiration:r})}return a};var l=e._getWebdavProperties;e._getWebdavProperties=function(){var e=l.apply(this,arguments);return e.push(OC.Files.Client.PROPERTY_OWNER_ID),e.push(OC.Files.Client.PROPERTY_OWNER_DISPLAY_NAME),e.push(OC.Files.Client.PROPERTY_SHARE_TYPES),e},e.filesClient.addFileInfoParser((function(e){var a={},r=e.propStat[0].properties,t=r[OC.Files.Client.PROPERTY_PERMISSIONS];t&&t.indexOf("S")>=0&&(a.shareOwner=r[OC.Files.Client.PROPERTY_OWNER_DISPLAY_NAME],a.shareOwnerId=r[OC.Files.Client.PROPERTY_OWNER_ID]);var i=r[OC.Files.Client.PROPERTY_SHARE_TYPES];return i&&(a.shareTypes=_.chain(i).filter((function(e){return e.namespaceURI===OC.Files.Client.NS_OWNCLOUD&&"share-type"===e.nodeName.split(":")[1]})).map((function(e){return parseInt(e.textContent||e.text,10)})).value()),a})),e.$el.on("fileActionsReady",(function(e){var a=e.$files;_.each(a,(function(e){var a=$(e),r=a.attr("data-share-types")||"",t=a.attr("data-share-owner");if(r||t){var i=!1,n=!1;_.each(r.split(",")||[],(function(e){let a=parseInt(e,10);a===s.D.SHARE_TYPE_LINK||a===s.D.SHARE_TYPE_EMAIL?i=!0:(a===s.D.SHARE_TYPE_USER||a===s.D.SHARE_TYPE_GROUP||a===s.D.SHARE_TYPE_REMOTE||a===s.D.SHARE_TYPE_REMOTE_GROUP||a===s.D.SHARE_TYPE_CIRCLE||a===s.D.SHARE_TYPE_ROOM||a===s.D.SHARE_TYPE_DECK||a===s.D.SHARE_TYPE_SCIENCEMESH)&&(n=!0)})),OCA.Sharing.Util._updateFileActionIcon(a,n,i)}}))})),e.$el.on("changeDirectory",(function(){OCA.Sharing.sharesLoaded=!1})),r.registerAction({name:"Share",displayName:function(e){if(e&&e.$file){var a=parseInt(e.$file.data("share-types"),10),r=e.$file.data("share-owner-id");if(a>=0||r)return t("files_sharing","Shared")}return t("files_sharing","Share")},altText:t("files_sharing","Share"),mime:"all",order:-150,permissions:OC.PERMISSION_ALL,iconClass:function(e,a){var r=parseInt(a.$file.data("share-types"),10);return r===s.D.SHARE_TYPE_EMAIL||r===s.D.SHARE_TYPE_LINK?"icon-public":"icon-shared"},icon:function(e,a){var r=a.$file.data("share-owner-id");if(r)return OC.generateUrl("/avatar/".concat(r,"/32"))},type:OCA.Files.FileActions.TYPE_INLINE,actionHandler:function(a,r){if(e._detailsView){var t=parseInt(r.$file.data("share-permissions"),10);(isNaN(t)||t>0)&&e.showDetailsView(a,"sharing")}},render:function(e,a,t){return 0!=(parseInt(t.$file.data("permissions"),10)&OC.PERMISSION_SHARE)||t.$file.attr("data-share-owner")?r._defaultRenderAction.call(r,e,a,t):null}});var d=new OCA.Sharing.ShareBreadCrumbView;e.registerBreadCrumbDetailView(d)}},_updateFileListDataAttributes:function(e,a,r){if("files"!==e.id)if(_.pluck(r.get("shares"),"share_with_displayname").length){var t=_.mapObject(r.get("shares"),(function(e){return{shareWith:e.share_with,shareWithDisplayName:e.share_with_displayname}}));a.attr("data-share-recipient-data",JSON.stringify(t))}else a.removeAttr("data-share-recipient-data")},_updateFileActionIcon:function(e,a,r){return!!(a||r||e.attr("data-share-recipient-data")||e.attr("data-share-owner"))&&(OCA.Sharing.Util._markFileAsShared(e,!0,r),!0)},_markFileAsShared:function(e,a,r){var i,n,s,o,l=e.find('.fileactions .action[data-action="Share"]'),d=e.data("type"),h=l.find(".icon"),c=e.attr("data-share-owner-id"),p=e.attr("data-share-owner"),u=e.attr("data-mounttype"),f="icon-shared";l.removeClass("shared-style");var m=e.attr("data-e2eencrypted");"dir"===d&&"true"===m?(o=OC.MimeType.getIconUrl("dir-encrypted"),e.attr("data-icon",o)):"dir"===d&&(a||r||c)?(o=void 0!==u&&"shared-root"!==u&&"shared"!==u?OC.MimeType.getIconUrl("dir-"+u):r?OC.MimeType.getIconUrl("dir-public"):OC.MimeType.getIconUrl("dir-shared"),e.find(".filename .thumbnail").css("background-image","url("+o+")"),e.attr("data-icon",o)):"dir"===d&&(u&&0===u.indexOf("external")?(o=OC.MimeType.getIconUrl("dir-external"),e.attr("data-icon",o)):(o=OC.MimeType.getIconUrl("dir"),e.removeAttr("data-icon")),e.find(".filename .thumbnail").css("background-image","url("+o+")")),a||c?(n=e.data("share-recipient-data"),l.addClass("shared-style"),s="<span>"+t("files_sharing","Shared")+"</span>",c?(i=t("files_sharing","Shared by"),s=OCA.Sharing.Util._formatRemoteShare(c,p,i)):n&&(s=OCA.Sharing.Util._formatShareList(n)),l.html(s).prepend(h),(c||n)&&l.find(".avatar").each((function(){$(this).avatar($(this).data("username"),32)}))):l.html('<span class="hidden-visually">'+t("files_sharing","Shared")+"</span>").prepend(h),r&&(f="icon-public"),h.removeClass("icon-shared icon-public").addClass(f)},_formatRemoteShare:function(e,a,r){var t=OCA.Sharing.Util._REMOTE_OWNER_REGEXP.exec(e);if(!t||!t[7])return'<span class="avatar" data-username="'+n()(e)+'" title="'+r+" "+n()(a)+'"></span><span class="hidden-visually">'+r+" "+n()(a)+"</span> ";var i=t[2],s=t[4],o=t[5],l=t[6],d=t[8]?t[7]:"",h=r+" "+i;s&&(h+="@"+s),o&&(h+="@"+o.replace(l,"")+d);var c='<span class="remoteAddress" title="'+n()(h)+'">';return c+='<span class="username">'+n()(i)+"</span>",s&&(c+='<span class="userDomain">@'+n()(s)+"</span>"),c+"</span> "},_formatShareList:function(e){var a=this;return(e=_.toArray(e)).sort((function(e,a){return e.shareWithDisplayName.localeCompare(a.shareWithDisplayName)})),$.map(e,(function(e){return a._formatRemoteShare(e.shareWith,e.shareWithDisplayName,t("files_sharing","Shared with"))}))},markFileAsShared:function(e,a,r){var i,n,s,o,l=e.find('.fileactions .action[data-action="Share"]'),d=e.data("type"),h=l.find(".icon"),c=e.attr("data-share-owner-id"),p=e.attr("data-share-owner"),u=e.attr("data-mounttype"),f="icon-shared";l.removeClass("shared-style"),"dir"===d&&(a||r||c)?(o=void 0!==u&&"shared-root"!==u&&"shared"!==u?OC.MimeType.getIconUrl("dir-"+u):r?OC.MimeType.getIconUrl("dir-public"):OC.MimeType.getIconUrl("dir-shared"),e.find(".filename .thumbnail").css("background-image","url("+o+")"),e.attr("data-icon",o)):"dir"===d&&("true"===e.attr("data-e2eencrypted")?(o=OC.MimeType.getIconUrl("dir-encrypted"),e.attr("data-icon",o)):u&&0===u.indexOf("external")?(o=OC.MimeType.getIconUrl("dir-external"),e.attr("data-icon",o)):(o=OC.MimeType.getIconUrl("dir"),e.removeAttr("data-icon")),e.find(".filename .thumbnail").css("background-image","url("+o+")")),a||c?(n=e.data("share-recipient-data"),l.addClass("shared-style"),s="<span>"+t("files_sharing","Shared")+"</span>",c?(i=t("files_sharing","Shared by"),s=this._formatRemoteShare(c,p,i)):n&&(s=this._formatShareList(n)),l.html(s).prepend(h),(c||n)&&l.find(".avatar").each((function(){$(this).avatar($(this).data("username"),32)}))):l.html('<span class="hidden-visually">'+t("files_sharing","Shared")+"</span>").prepend(h),r&&(f="icon-public"),h.removeClass("icon-shared icon-public").addClass(f)},getSharePermissions:function(e){return e.sharePermissions}},OC.Plugins.register("OCA.Files.FileList",OCA.Sharing.Util),function(){const e=OC.Backbone.View.extend({tagName:"span",events:{click:"_onClick"},_dirInfo:void 0,render(e){if(this._dirInfo=e.dirInfo||null,null===this._dirInfo||"/"===this._dirInfo.path&&""===this._dirInfo.name)this.$el.removeClass("shared icon-public icon-shared"),this.$el.hide();else{const a=e.dirInfo&&e.dirInfo.shareTypes&&e.dirInfo.shareTypes.length>0;this.$el.removeClass("shared icon-public icon-shared"),a?(this.$el.addClass("shared"),-1!==e.dirInfo.shareTypes.indexOf(s.D.SHARE_TYPE_LINK)?this.$el.addClass("icon-public"):this.$el.addClass("icon-shared")):this.$el.addClass("icon-shared"),this.$el.show(),this.delegateEvents()}return this},_onClick(e){e.preventDefault(),e.stopPropagation();const a=new OCA.Files.FileInfoModel(this._dirInfo),r=this;a.on("change",(function(){r.render({dirInfo:r._dirInfo})}));const t=a.attributes.path+"/"+a.attributes.name;OCA.Files.Sidebar.open(t),OCA.Files.Sidebar.setActiveTab("sharing")}});OCA.Sharing.ShareBreadCrumbView=e}();var l=r(93379),d=r.n(l),h=r(7795),c=r.n(h),p=r(90569),u=r.n(p),f=r(3565),m=r.n(f),O=r(19216),C=r.n(O),A=r(44589),g=r.n(A),S=r(89216),y={};y.styleTagTransform=g(),y.setAttributes=m(),y.insert=u().bind(null,"head"),y.domAPI=c(),y.insertStyleElement=C(),d()(S.Z,y),S.Z&&S.Z.locals&&S.Z.locals,r(18730),r.nc=btoa(OC.requestToken),window.OCA.Sharing=OCA.Sharing},18730:(e,a,r)=>{r.nc=btoa(OC.requestToken),window.OCP.Collaboration.registerType("file",{action:()=>new Promise(((e,a)=>{OC.dialogs.filepicker(t("files_sharing","Link to a file"),(function(r){OC.Files.getClient().getFileInfo(r).then(((a,r)=>{e(r.id)})).fail((()=>{a(new Error("Cannot get fileinfo"))}))}),!1,null,!1,OC.dialogs.FILEPICKER_TYPE_CHOOSE,"",{allowDirectoryChooser:!0})})),typeString:t("files_sharing","Link to a file"),typeIconClass:"icon-files-dark"})},89216:(e,a,r)=>{"use strict";r.d(a,{Z:()=>o});var t=r(87537),i=r.n(t),n=r(23645),s=r.n(n)()(i());s.push([e.id,"li.crumb span.icon-shared,li.crumb span.icon-public{display:inline-block;cursor:pointer;opacity:.2;margin-right:6px}li.crumb span.icon-shared.shared,li.crumb span.icon-public.shared{opacity:.7}","",{version:3,sources:["webpack://./apps/files_sharing/src/style/sharebreadcrumb.scss"],names:[],mappings:"AAsBA,oDAEC,oBAAA,CACA,cAAA,CACA,UAAA,CACA,gBAAA,CAGD,kEAEC,UAAA",sourcesContent:["/**\n * @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>\n *\n * @author 2016 Christoph Wurst <christoph@winzerhof-wurst.at>\n *\n * @license GNU AGPL version 3 or any later version\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nli.crumb span.icon-shared,\nli.crumb span.icon-public {\n\tdisplay: inline-block;\n\tcursor: pointer;\n\topacity: 0.2;\n\tmargin-right: 6px;\n}\n\nli.crumb span.icon-shared.shared,\nli.crumb span.icon-public.shared {\n\topacity: 0.7;\n}\n"],sourceRoot:""}]);const o=s}},r={};function i(e){var t=r[e];if(void 0!==t)return t.exports;var n=r[e]={id:e,loaded:!1,exports:{}};return a[e].call(n.exports,n,n.exports,i),n.loaded=!0,n.exports}i.m=a,e=[],i.O=(a,r,t,n)=>{if(!r){var s=1/0;for(h=0;h<e.length;h++){r=e[h][0],t=e[h][1],n=e[h][2];for(var o=!0,l=0;l<r.length;l++)(!1&n||s>=n)&&Object.keys(i.O).every((e=>i.O[e](r[l])))?r.splice(l--,1):(o=!1,n<s&&(s=n));if(o){e.splice(h--,1);var d=t();void 0!==d&&(a=d)}}return a}n=n||0;for(var h=e.length;h>0&&e[h-1][2]>n;h--)e[h]=e[h-1];e[h]=[r,t,n]},i.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return i.d(a,{a}),a},i.d=(e,a)=>{for(var r in a)i.o(a,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:a[r]})},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),i.j=6200,(()=>{i.b=document.baseURI||self.location.href;var e={6200:0,5438:0};i.O.j=a=>0===e[a];var a=(a,r)=>{var t,n,s=r[0],o=r[1],l=r[2],d=0;if(s.some((a=>0!==e[a]))){for(t in o)i.o(o,t)&&(i.m[t]=o[t]);if(l)var h=l(i)}for(a&&a(r);d<s.length;d++)n=s[d],i.o(e,n)&&e[n]&&e[n][0](),e[n]=0;return i.O(h)},r=self.webpackChunknextcloud=self.webpackChunknextcloud||[];r.forEach(a.bind(null,0)),r.push=a.bind(null,r.push.bind(r))})(),i.nc=void 0;var n=i.O(void 0,[7874],(()=>i(5972)));n=i.O(n)})();
-//# sourceMappingURL=files_sharing-additionalScripts.js.map?v=88639154de39b79d7100 \ No newline at end of file
+(()=>{var e,a={5972:(e,a,r)=>{"use strict";var i=r(95573),n=r.n(i),s=r(41922),o=r(42515);_.extend(OC.Files.Client,{PROPERTY_SHARE_TYPES:"{"+OC.Files.Client.NS_OWNCLOUD+"}share-types",PROPERTY_OWNER_ID:"{"+OC.Files.Client.NS_OWNCLOUD+"}owner-id",PROPERTY_OWNER_DISPLAY_NAME:"{"+OC.Files.Client.NS_OWNCLOUD+"}owner-display-name"}),OCA.Sharing||(OCA.Sharing={}),OCA.Sharing.Util={_REMOTE_OWNER_REGEXP:new RegExp("^(([^@]*)@(([^@^/\\s]*)@)?)((https://)?[^[\\s/]*)([/](.*))?$"),attach:function(e){var a;if(null!==(a=(0,o.getCapabilities)().files_sharing)&&void 0!==a&&a.api_enabled&&"trashbin"!==e.id&&"files.public"!==e.id){var r=e.fileActions,i=e._createRow;e._createRow=function(e){var a=i.apply(this,arguments),t=OCA.Sharing.Util.getSharePermissions(e);return 0===e.permissions&&(delete r.actions.all.Comment,delete r.actions.all.Details,delete r.actions.all.Goto),_.isFunction(e.canDownload)&&!e.canDownload()&&(delete r.actions.all.Download,0==(e.permissions&OC.PERMISSION_UPDATE)&&delete r.actions.all.MoveCopy),a.attr("data-share-permissions",t),a.attr("data-share-attributes",JSON.stringify(e.shareAttributes)),e.shareOwner&&(a.attr("data-share-owner",e.shareOwner),a.attr("data-share-owner-id",e.shareOwnerId),"shared-root"===e.mountType&&a.attr("data-permissions",e.permissions|OC.PERMISSION_UPDATE)),e.recipientData&&!_.isEmpty(e.recipientData)&&a.attr("data-share-recipient-data",JSON.stringify(e.recipientData)),e.shareTypes&&a.attr("data-share-types",e.shareTypes.join(",")),a};var n=e.elementToFile;e.elementToFile=function(e){var a=n.apply(this,arguments);if(a.shareAttributes=JSON.parse(e.attr("data-share-attributes")||"[]"),a.sharePermissions=e.attr("data-share-permissions")||void 0,a.shareOwner=e.attr("data-share-owner")||void 0,a.shareOwnerId=e.attr("data-share-owner-id")||void 0,e.attr("data-share-types")&&(a.shareTypes=e.attr("data-share-types").split(",")),e.attr("data-expiration")){var r=parseInt(e.attr("data-expiration"));a.shares=[],a.shares.push({expiration:r})}return a};var l=e._getWebdavProperties;e._getWebdavProperties=function(){var e=l.apply(this,arguments);return e.push(OC.Files.Client.PROPERTY_OWNER_ID),e.push(OC.Files.Client.PROPERTY_OWNER_DISPLAY_NAME),e.push(OC.Files.Client.PROPERTY_SHARE_TYPES),e},e.filesClient.addFileInfoParser((function(e){var a={},r=e.propStat[0].properties,t=r[OC.Files.Client.PROPERTY_PERMISSIONS];t&&t.indexOf("S")>=0&&(a.shareOwner=r[OC.Files.Client.PROPERTY_OWNER_DISPLAY_NAME],a.shareOwnerId=r[OC.Files.Client.PROPERTY_OWNER_ID]);var i=r[OC.Files.Client.PROPERTY_SHARE_TYPES];return i&&(a.shareTypes=_.chain(i).filter((function(e){return e.namespaceURI===OC.Files.Client.NS_OWNCLOUD&&"share-type"===e.nodeName.split(":")[1]})).map((function(e){return parseInt(e.textContent||e.text,10)})).value()),a})),e.$el.on("fileActionsReady",(function(e){var a=e.$files;_.each(a,(function(e){var a=$(e),r=a.attr("data-share-types")||"",t=a.attr("data-share-owner");if(r||t){var i=!1,n=!1;_.each(r.split(",")||[],(function(e){let a=parseInt(e,10);a===s.D.SHARE_TYPE_LINK||a===s.D.SHARE_TYPE_EMAIL?i=!0:(a===s.D.SHARE_TYPE_USER||a===s.D.SHARE_TYPE_GROUP||a===s.D.SHARE_TYPE_REMOTE||a===s.D.SHARE_TYPE_REMOTE_GROUP||a===s.D.SHARE_TYPE_CIRCLE||a===s.D.SHARE_TYPE_ROOM||a===s.D.SHARE_TYPE_DECK||a===s.D.SHARE_TYPE_SCIENCEMESH)&&(n=!0)})),OCA.Sharing.Util._updateFileActionIcon(a,n,i)}}))})),e.$el.on("changeDirectory",(function(){OCA.Sharing.sharesLoaded=!1})),r.registerAction({name:"Share",displayName:function(e){if(e&&e.$file){var a=parseInt(e.$file.data("share-types"),10),r=e.$file.data("share-owner-id");if(a>=0||r)return t("files_sharing","Shared")}return t("files_sharing","Share")},altText:t("files_sharing","Share"),mime:"all",order:-150,permissions:OC.PERMISSION_ALL,iconClass:function(e,a){var r=parseInt(a.$file.data("share-types"),10);return r===s.D.SHARE_TYPE_EMAIL||r===s.D.SHARE_TYPE_LINK?"icon-public":"icon-shared"},icon:function(e,a){var r=a.$file.data("share-owner-id");if(r)return OC.generateUrl("/avatar/".concat(r,"/32"))},type:OCA.Files.FileActions.TYPE_INLINE,actionHandler:function(a,r){if(e._detailsView){var t=parseInt(r.$file.data("share-permissions"),10);(isNaN(t)||t>0)&&e.showDetailsView(a,"sharing")}},render:function(e,a,t){return 0!=(parseInt(t.$file.data("permissions"),10)&OC.PERMISSION_SHARE)||t.$file.attr("data-share-owner")?r._defaultRenderAction.call(r,e,a,t):null}});var d=new OCA.Sharing.ShareBreadCrumbView;e.registerBreadCrumbDetailView(d)}},_updateFileListDataAttributes:function(e,a,r){if("files"!==e.id)if(_.pluck(r.get("shares"),"share_with_displayname").length){var t=_.mapObject(r.get("shares"),(function(e){return{shareWith:e.share_with,shareWithDisplayName:e.share_with_displayname}}));a.attr("data-share-recipient-data",JSON.stringify(t))}else a.removeAttr("data-share-recipient-data")},_updateFileActionIcon:function(e,a,r){return!!(a||r||e.attr("data-share-recipient-data")||e.attr("data-share-owner"))&&(OCA.Sharing.Util._markFileAsShared(e,!0,r),!0)},_markFileAsShared:function(e,a,r){var i,n,s,o,l=e.find('.fileactions .action[data-action="Share"]'),d=e.data("type"),h=l.find(".icon"),c=e.attr("data-share-owner-id"),p=e.attr("data-share-owner"),u=e.attr("data-mounttype"),f="icon-shared";l.removeClass("shared-style");var m=e.attr("data-e2eencrypted");"dir"===d&&"true"===m?(o=OC.MimeType.getIconUrl("dir-encrypted"),e.attr("data-icon",o)):"dir"===d&&(a||r||c)?(o=void 0!==u&&"shared-root"!==u&&"shared"!==u?OC.MimeType.getIconUrl("dir-"+u):r?OC.MimeType.getIconUrl("dir-public"):OC.MimeType.getIconUrl("dir-shared"),e.find(".filename .thumbnail").css("background-image","url("+o+")"),e.attr("data-icon",o)):"dir"===d&&(u&&0===u.indexOf("external")?(o=OC.MimeType.getIconUrl("dir-external"),e.attr("data-icon",o)):(o=OC.MimeType.getIconUrl("dir"),e.removeAttr("data-icon")),e.find(".filename .thumbnail").css("background-image","url("+o+")")),a||c?(n=e.data("share-recipient-data"),l.addClass("shared-style"),s="<span>"+t("files_sharing","Shared")+"</span>",c?(i=t("files_sharing","Shared by"),s=OCA.Sharing.Util._formatRemoteShare(c,p,i)):n&&(s=OCA.Sharing.Util._formatShareList(n)),l.html(s).prepend(h),(c||n)&&l.find(".avatar").each((function(){$(this).avatar($(this).data("username"),32)}))):l.html('<span class="hidden-visually">'+t("files_sharing","Shared")+"</span>").prepend(h),r&&(f="icon-public"),h.removeClass("icon-shared icon-public").addClass(f)},_formatRemoteShare:function(e,a,r){var t=OCA.Sharing.Util._REMOTE_OWNER_REGEXP.exec(e);if(!t||!t[7])return'<span class="avatar" data-username="'+n()(e)+'" title="'+r+" "+n()(a)+'"></span><span class="hidden-visually">'+r+" "+n()(a)+"</span> ";var i=t[2],s=t[4],o=t[5],l=t[6],d=t[8]?t[7]:"",h=r+" "+i;s&&(h+="@"+s),o&&(h+="@"+o.replace(l,"")+d);var c='<span class="remoteAddress" title="'+n()(h)+'">';return c+='<span class="username">'+n()(i)+"</span>",s&&(c+='<span class="userDomain">@'+n()(s)+"</span>"),c+"</span> "},_formatShareList:function(e){var a=this;return(e=_.toArray(e)).sort((function(e,a){return e.shareWithDisplayName.localeCompare(a.shareWithDisplayName)})),$.map(e,(function(e){return a._formatRemoteShare(e.shareWith,e.shareWithDisplayName,t("files_sharing","Shared with"))}))},markFileAsShared:function(e,a,r){var i,n,s,o,l=e.find('.fileactions .action[data-action="Share"]'),d=e.data("type"),h=l.find(".icon"),c=e.attr("data-share-owner-id"),p=e.attr("data-share-owner"),u=e.attr("data-mounttype"),f="icon-shared";l.removeClass("shared-style"),"dir"===d&&(a||r||c)?(o=void 0!==u&&"shared-root"!==u&&"shared"!==u?OC.MimeType.getIconUrl("dir-"+u):r?OC.MimeType.getIconUrl("dir-public"):OC.MimeType.getIconUrl("dir-shared"),e.find(".filename .thumbnail").css("background-image","url("+o+")"),e.attr("data-icon",o)):"dir"===d&&("true"===e.attr("data-e2eencrypted")?(o=OC.MimeType.getIconUrl("dir-encrypted"),e.attr("data-icon",o)):u&&0===u.indexOf("external")?(o=OC.MimeType.getIconUrl("dir-external"),e.attr("data-icon",o)):(o=OC.MimeType.getIconUrl("dir"),e.removeAttr("data-icon")),e.find(".filename .thumbnail").css("background-image","url("+o+")")),a||c?(n=e.data("share-recipient-data"),l.addClass("shared-style"),s="<span>"+t("files_sharing","Shared")+"</span>",c?(i=t("files_sharing","Shared by"),s=this._formatRemoteShare(c,p,i)):n&&(s=this._formatShareList(n)),l.html(s).prepend(h),(c||n)&&l.find(".avatar").each((function(){$(this).avatar($(this).data("username"),32)}))):l.html('<span class="hidden-visually">'+t("files_sharing","Shared")+"</span>").prepend(h),r&&(f="icon-public"),h.removeClass("icon-shared icon-public").addClass(f)},getSharePermissions:function(e){return e.sharePermissions}},OC.Plugins.register("OCA.Files.FileList",OCA.Sharing.Util),function(){const e=OC.Backbone.View.extend({tagName:"span",events:{click:"_onClick"},_dirInfo:void 0,render(e){if(this._dirInfo=e.dirInfo||null,null===this._dirInfo||"/"===this._dirInfo.path&&""===this._dirInfo.name)this.$el.removeClass("shared icon-public icon-shared"),this.$el.hide();else{const a=e.dirInfo&&e.dirInfo.shareTypes&&e.dirInfo.shareTypes.length>0;this.$el.removeClass("shared icon-public icon-shared"),a?(this.$el.addClass("shared"),-1!==e.dirInfo.shareTypes.indexOf(s.D.SHARE_TYPE_LINK)?this.$el.addClass("icon-public"):this.$el.addClass("icon-shared")):this.$el.addClass("icon-shared"),this.$el.show(),this.delegateEvents()}return this},_onClick(e){e.preventDefault(),e.stopPropagation();const a=new OCA.Files.FileInfoModel(this._dirInfo),r=this;a.on("change",(function(){r.render({dirInfo:r._dirInfo})}));const t=a.attributes.path+"/"+a.attributes.name;OCA.Files.Sidebar.open(t),OCA.Files.Sidebar.setActiveTab("sharing")}});OCA.Sharing.ShareBreadCrumbView=e}();var l=r(93379),d=r.n(l),h=r(7795),c=r.n(h),p=r(90569),u=r.n(p),f=r(3565),m=r.n(f),O=r(19216),C=r.n(O),A=r(44589),g=r.n(A),S=r(89216),y={};y.styleTagTransform=g(),y.setAttributes=m(),y.insert=u().bind(null,"head"),y.domAPI=c(),y.insertStyleElement=C(),d()(S.Z,y),S.Z&&S.Z.locals&&S.Z.locals,r(18730),r.nc=btoa(OC.requestToken),window.OCA.Sharing=OCA.Sharing},18730:(e,a,r)=>{r.nc=btoa(OC.requestToken),window.OCP.Collaboration.registerType("file",{action:()=>new Promise(((e,a)=>{OC.dialogs.filepicker(t("files_sharing","Link to a file"),(function(r){OC.Files.getClient().getFileInfo(r).then(((a,r)=>{e(r.id)})).fail((()=>{a(new Error("Cannot get fileinfo"))}))}),!1,null,!1,OC.dialogs.FILEPICKER_TYPE_CHOOSE,"",{allowDirectoryChooser:!0})})),typeString:t("files_sharing","Link to a file"),typeIconClass:"icon-files-dark"})},89216:(e,a,r)=>{"use strict";r.d(a,{Z:()=>o});var t=r(87537),i=r.n(t),n=r(23645),s=r.n(n)()(i());s.push([e.id,"li.crumb span.icon-shared,li.crumb span.icon-public{display:inline-block;cursor:pointer;opacity:.2;margin-right:6px}li.crumb span.icon-shared.shared,li.crumb span.icon-public.shared{opacity:.7}","",{version:3,sources:["webpack://./apps/files_sharing/src/style/sharebreadcrumb.scss"],names:[],mappings:"AAsBA,oDAEC,oBAAA,CACA,cAAA,CACA,UAAA,CACA,gBAAA,CAGD,kEAEC,UAAA",sourcesContent:["/**\n * @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>\n *\n * @author 2016 Christoph Wurst <christoph@winzerhof-wurst.at>\n *\n * @license GNU AGPL version 3 or any later version\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nli.crumb span.icon-shared,\nli.crumb span.icon-public {\n\tdisplay: inline-block;\n\tcursor: pointer;\n\topacity: 0.2;\n\tmargin-right: 6px;\n}\n\nli.crumb span.icon-shared.shared,\nli.crumb span.icon-public.shared {\n\topacity: 0.7;\n}\n"],sourceRoot:""}]);const o=s}},r={};function i(e){var t=r[e];if(void 0!==t)return t.exports;var n=r[e]={id:e,loaded:!1,exports:{}};return a[e].call(n.exports,n,n.exports,i),n.loaded=!0,n.exports}i.m=a,e=[],i.O=(a,r,t,n)=>{if(!r){var s=1/0;for(h=0;h<e.length;h++){r=e[h][0],t=e[h][1],n=e[h][2];for(var o=!0,l=0;l<r.length;l++)(!1&n||s>=n)&&Object.keys(i.O).every((e=>i.O[e](r[l])))?r.splice(l--,1):(o=!1,n<s&&(s=n));if(o){e.splice(h--,1);var d=t();void 0!==d&&(a=d)}}return a}n=n||0;for(var h=e.length;h>0&&e[h-1][2]>n;h--)e[h]=e[h-1];e[h]=[r,t,n]},i.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return i.d(a,{a}),a},i.d=(e,a)=>{for(var r in a)i.o(a,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:a[r]})},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),i.j=6200,(()=>{i.b=document.baseURI||self.location.href;var e={6200:0,5438:0};i.O.j=a=>0===e[a];var a=(a,r)=>{var t,n,s=r[0],o=r[1],l=r[2],d=0;if(s.some((a=>0!==e[a]))){for(t in o)i.o(o,t)&&(i.m[t]=o[t]);if(l)var h=l(i)}for(a&&a(r);d<s.length;d++)n=s[d],i.o(e,n)&&e[n]&&e[n][0](),e[n]=0;return i.O(h)},r=self.webpackChunknextcloud=self.webpackChunknextcloud||[];r.forEach(a.bind(null,0)),r.push=a.bind(null,r.push.bind(r))})(),i.nc=void 0;var n=i.O(void 0,[7874],(()=>i(5972)));n=i.O(n)})();
+//# sourceMappingURL=files_sharing-additionalScripts.js.map?v=4048ce644c9ad516a624 \ No newline at end of file
diff --git a/dist/files_sharing-additionalScripts.js.map b/dist/files_sharing-additionalScripts.js.map
index db0ab707db2..017a919a116 100644
--- a/dist/files_sharing-additionalScripts.js.map
+++ b/dist/files_sharing-additionalScripts.js.map
@@ -1 +1 @@
-{"version":3,"file":"files_sharing-additionalScripts.js?v=88639154de39b79d7100","mappings":"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","sources":["webpack:///nextcloud/webpack/runtime/chunk loaded","webpack:///nextcloud/apps/files_sharing/src/share.js","webpack:///nextcloud/apps/files_sharing/src/sharebreadcrumbview.js","webpack://nextcloud/./apps/files_sharing/src/style/sharebreadcrumb.scss?a9a3","webpack:///nextcloud/apps/files_sharing/src/additionalScripts.js","webpack:///nextcloud/apps/files_sharing/src/collaborationresourceshandler.js","webpack:///nextcloud/apps/files_sharing/src/style/sharebreadcrumb.scss","webpack:///nextcloud/webpack/bootstrap","webpack:///nextcloud/webpack/runtime/compat get default export","webpack:///nextcloud/webpack/runtime/define property getters","webpack:///nextcloud/webpack/runtime/global","webpack:///nextcloud/webpack/runtime/hasOwnProperty shorthand","webpack:///nextcloud/webpack/runtime/make namespace object","webpack:///nextcloud/webpack/runtime/node module decorator","webpack:///nextcloud/webpack/runtime/runtimeId","webpack:///nextcloud/webpack/runtime/jsonp chunk loading","webpack:///nextcloud/webpack/runtime/nonce","webpack:///nextcloud/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","/**\n * Copyright (c) 2014\n *\n * @author Arthur Schiwon <blizzz@arthur-schiwon.de>\n * @author Christoph Wurst <christoph@winzerhof-wurst.at>\n * @author Daniel Calviño Sánchez <danxuliu@gmail.com>\n * @author Joas Schilling <coding@schilljs.com>\n * @author John Molakvoæ <skjnldsv@protonmail.com>\n * @author Julius Härtl <jus@bitgrid.net>\n * @author Maxence Lange <maxence@nextcloud.com>\n * @author Michael Jobst <mjobst+github@tecratech.de>\n * @author Michael Jobst <mjobst@necls.com>\n * @author Morris Jobke <hey@morrisjobke.de>\n * @author Roeland Jago Douma <roeland@famdouma.nl>\n * @author Samuel <faust64@gmail.com>\n * @author Vincent Petry <vincent@nextcloud.com>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\n/* eslint-disable */\nimport escapeHTML from 'escape-html'\n\nimport { Type as ShareTypes } from '@nextcloud/sharing'\nimport { getCapabilities } from '@nextcloud/capabilities'\n\n(function() {\n\n\t_.extend(OC.Files.Client, {\n\t\tPROPERTY_SHARE_TYPES:\t'{' + OC.Files.Client.NS_OWNCLOUD + '}share-types',\n\t\tPROPERTY_OWNER_ID:\t'{' + OC.Files.Client.NS_OWNCLOUD + '}owner-id',\n\t\tPROPERTY_OWNER_DISPLAY_NAME:\t'{' + OC.Files.Client.NS_OWNCLOUD + '}owner-display-name'\n\t})\n\n\tif (!OCA.Sharing) {\n\t\tOCA.Sharing = {}\n\t}\n\n\t/**\n\t * @namespace\n\t */\n\tOCA.Sharing.Util = {\n\n\t\t/**\n\t\t * Regular expression for splitting parts of remote share owners:\n\t\t * \"user@example.com/\"\n\t\t * \"user@example.com/path/to/owncloud\"\n\t\t * \"user@anotherexample.com@example.com/path/to/owncloud\n\t\t */\n\t\t_REMOTE_OWNER_REGEXP: new RegExp('^(([^@]*)@(([^@^/\\\\s]*)@)?)((https://)?[^[\\\\s/]*)([/](.*))?$'),\n\n\t\t/**\n\t\t * Initialize the sharing plugin.\n\t\t *\n\t\t * Registers the \"Share\" file action and adds additional\n\t\t * DOM attributes for the sharing file info.\n\t\t *\n\t\t * @param {OCA.Files.FileList} fileList file list to be extended\n\t\t */\n\t\tattach: function(fileList) {\n\t\t\t// core sharing is disabled/not loaded\n\t\t\tif (!getCapabilities().files_sharing?.api_enabled) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (fileList.id === 'trashbin' || fileList.id === 'files.public') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvar fileActions = fileList.fileActions\n\t\t\tvar oldCreateRow = fileList._createRow\n\t\t\tfileList._createRow = function(fileData) {\n\n\t\t\t\tvar tr = oldCreateRow.apply(this, arguments)\n\t\t\t\tvar sharePermissions = OCA.Sharing.Util.getSharePermissions(fileData)\n\n\t\t\t\tif (fileData.permissions === 0) {\n\t\t\t\t\t// no permission, disabling sidebar\n\t\t\t\t\tdelete fileActions.actions.all.Comment\n\t\t\t\t\tdelete fileActions.actions.all.Details\n\t\t\t\t\tdelete fileActions.actions.all.Goto\n\t\t\t\t}\n\t\t\t\tif (_.isFunction(fileData.canDownload) && !fileData.canDownload()) {\n\t\t\t\t\tdelete fileActions.actions.all.Download\n\t\t\t\t\tif (fileData.permissions & OC.PERMISSION_UPDATE === 0) {\n\t\t\t\t\t\t// neither move nor copy is allowed, remove the action completely\n\t\t\t\t\t\tdelete fileActions.actions.all.MoveCopy\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttr.attr('data-share-permissions', sharePermissions)\n\t\t\t\ttr.attr('data-share-attributes', JSON.stringify(fileData.shareAttributes))\n\t\t\t\tif (fileData.shareOwner) {\n\t\t\t\t\ttr.attr('data-share-owner', fileData.shareOwner)\n\t\t\t\t\ttr.attr('data-share-owner-id', fileData.shareOwnerId)\n\t\t\t\t\t// user should always be able to rename a mount point\n\t\t\t\t\tif (fileData.mountType === 'shared-root') {\n\t\t\t\t\t\ttr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (fileData.recipientData && !_.isEmpty(fileData.recipientData)) {\n\t\t\t\t\ttr.attr('data-share-recipient-data', JSON.stringify(fileData.recipientData))\n\t\t\t\t}\n\t\t\t\tif (fileData.shareTypes) {\n\t\t\t\t\ttr.attr('data-share-types', fileData.shareTypes.join(','))\n\t\t\t\t}\n\t\t\t\treturn tr\n\t\t\t}\n\n\t\t\tvar oldElementToFile = fileList.elementToFile\n\t\t\tfileList.elementToFile = function($el) {\n\t\t\t\tvar fileInfo = oldElementToFile.apply(this, arguments)\n\t\t\t\tfileInfo.shareAttributes = JSON.parse($el.attr('data-share-attributes') || '[]')\n\t\t\t\tfileInfo.sharePermissions = $el.attr('data-share-permissions') || undefined\n\t\t\t\tfileInfo.shareOwner = $el.attr('data-share-owner') || undefined\n\t\t\t\tfileInfo.shareOwnerId = $el.attr('data-share-owner-id') || undefined\n\n\t\t\t\tif ($el.attr('data-share-types')) {\n\t\t\t\t\tfileInfo.shareTypes = $el.attr('data-share-types').split(',')\n\t\t\t\t}\n\n\t\t\t\tif ($el.attr('data-expiration')) {\n\t\t\t\t\tvar expirationTimestamp = parseInt($el.attr('data-expiration'))\n\t\t\t\t\tfileInfo.shares = []\n\t\t\t\t\tfileInfo.shares.push({ expiration: expirationTimestamp })\n\t\t\t\t}\n\n\t\t\t\treturn fileInfo\n\t\t\t}\n\n\t\t\tvar oldGetWebdavProperties = fileList._getWebdavProperties\n\t\t\tfileList._getWebdavProperties = function() {\n\t\t\t\tvar props = oldGetWebdavProperties.apply(this, arguments)\n\t\t\t\tprops.push(OC.Files.Client.PROPERTY_OWNER_ID)\n\t\t\t\tprops.push(OC.Files.Client.PROPERTY_OWNER_DISPLAY_NAME)\n\t\t\t\tprops.push(OC.Files.Client.PROPERTY_SHARE_TYPES)\n\t\t\t\treturn props\n\t\t\t}\n\n\t\t\tfileList.filesClient.addFileInfoParser(function(response) {\n\t\t\t\tvar data = {}\n\t\t\t\tvar props = response.propStat[0].properties\n\t\t\t\tvar permissionsProp = props[OC.Files.Client.PROPERTY_PERMISSIONS]\n\n\t\t\t\tif (permissionsProp && permissionsProp.indexOf('S') >= 0) {\n\t\t\t\t\tdata.shareOwner = props[OC.Files.Client.PROPERTY_OWNER_DISPLAY_NAME]\n\t\t\t\t\tdata.shareOwnerId = props[OC.Files.Client.PROPERTY_OWNER_ID]\n\t\t\t\t}\n\n\t\t\t\tvar shareTypesProp = props[OC.Files.Client.PROPERTY_SHARE_TYPES]\n\t\t\t\tif (shareTypesProp) {\n\t\t\t\t\tdata.shareTypes = _.chain(shareTypesProp).filter(function(xmlvalue) {\n\t\t\t\t\t\treturn (xmlvalue.namespaceURI === OC.Files.Client.NS_OWNCLOUD && xmlvalue.nodeName.split(':')[1] === 'share-type')\n\t\t\t\t\t}).map(function(xmlvalue) {\n\t\t\t\t\t\treturn parseInt(xmlvalue.textContent || xmlvalue.text, 10)\n\t\t\t\t\t}).value()\n\t\t\t\t}\n\n\t\t\t\treturn data\n\t\t\t})\n\n\t\t\t// use delegate to catch the case with multiple file lists\n\t\t\tfileList.$el.on('fileActionsReady', function(ev) {\n\t\t\t\tvar $files = ev.$files\n\n\t\t\t\t_.each($files, function(file) {\n\t\t\t\t\tvar $tr = $(file)\n\t\t\t\t\tvar shareTypesStr = $tr.attr('data-share-types') || ''\n\t\t\t\t\tvar shareOwner = $tr.attr('data-share-owner')\n\t\t\t\t\tif (shareTypesStr || shareOwner) {\n\t\t\t\t\t\tvar hasLink = false\n\t\t\t\t\t\tvar hasShares = false\n\t\t\t\t\t\t_.each(shareTypesStr.split(',') || [], function(shareTypeStr) {\n\t\t\t\t\t\t\tlet shareType = parseInt(shareTypeStr, 10)\n\t\t\t\t\t\t\tif (shareType === ShareTypes.SHARE_TYPE_LINK) {\n\t\t\t\t\t\t\t\thasLink = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_EMAIL) {\n\t\t\t\t\t\t\t\thasLink = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_USER) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_GROUP) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_REMOTE) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_REMOTE_GROUP) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_CIRCLE) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_ROOM) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_DECK) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_SCIENCEMESH) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\tOCA.Sharing.Util._updateFileActionIcon($tr, hasShares, hasLink)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\n\t\t\tfileList.$el.on('changeDirectory', function() {\n\t\t\t\tOCA.Sharing.sharesLoaded = false\n\t\t\t})\n\n\t\t\tfileActions.registerAction({\n\t\t\t\tname: 'Share',\n\t\t\t\tdisplayName: function(context) {\n\t\t\t\t\tif (context && context.$file) {\n\t\t\t\t\t\tvar shareType = parseInt(context.$file.data('share-types'), 10)\n\t\t\t\t\t\tvar shareOwner = context.$file.data('share-owner-id')\n\t\t\t\t\t\tif (shareType >= 0 || shareOwner) {\n\t\t\t\t\t\t\treturn t('files_sharing', 'Shared')\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn t('files_sharing', 'Share')\n\t\t\t\t},\n\t\t\t\taltText: t('files_sharing', 'Share'),\n\t\t\t\tmime: 'all',\n\t\t\t\torder: -150,\n\t\t\t\tpermissions: OC.PERMISSION_ALL,\n\t\t\t\ticonClass: function(fileName, context) {\n\t\t\t\t\tvar shareType = parseInt(context.$file.data('share-types'), 10)\n\t\t\t\t\tif (shareType === ShareTypes.SHARE_TYPE_EMAIL\n\t\t\t\t\t\t|| shareType === ShareTypes.SHARE_TYPE_LINK) {\n\t\t\t\t\t\treturn 'icon-public'\n\t\t\t\t\t}\n\t\t\t\t\treturn 'icon-shared'\n\t\t\t\t},\n\t\t\t\ticon: function(fileName, context) {\n\t\t\t\t\tvar shareOwner = context.$file.data('share-owner-id')\n\t\t\t\t\tif (shareOwner) {\n\t\t\t\t\t\treturn OC.generateUrl(`/avatar/${shareOwner}/32`)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\ttype: OCA.Files.FileActions.TYPE_INLINE,\n\t\t\t\tactionHandler: function(fileName, context) {\n\t\t\t\t\t// details view disabled in some share lists\n\t\t\t\t\tif (!fileList._detailsView) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// do not open sidebar if permission is set and equal to 0\n\t\t\t\t\tvar permissions = parseInt(context.$file.data('share-permissions'), 10)\n\t\t\t\t\tif (isNaN(permissions) || permissions > 0) {\n\t\t\t\t\t\tfileList.showDetailsView(fileName, 'sharing')\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\trender: function(actionSpec, isDefault, context) {\n\t\t\t\t\tvar permissions = parseInt(context.$file.data('permissions'), 10)\n\t\t\t\t\t// if no share permissions but share owner exists, still show the link\n\t\t\t\t\tif ((permissions & OC.PERMISSION_SHARE) !== 0 || context.$file.attr('data-share-owner')) {\n\t\t\t\t\t\treturn fileActions._defaultRenderAction.call(fileActions, actionSpec, isDefault, context)\n\t\t\t\t\t}\n\t\t\t\t\t// don't render anything\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t})\n\n\t\t\t// register share breadcrumbs component\n\t\t\tvar breadCrumbSharingDetailView = new OCA.Sharing.ShareBreadCrumbView()\n\t\t\tfileList.registerBreadCrumbDetailView(breadCrumbSharingDetailView)\n\t\t},\n\n\t\t/**\n\t\t * Update file list data attributes\n\t\t */\n\t\t_updateFileListDataAttributes: function(fileList, $tr, shareModel) {\n\t\t\t// files app current cannot show recipients on load, so we don't update the\n\t\t\t// icon when changed for consistency\n\t\t\tif (fileList.id === 'files') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvar recipients = _.pluck(shareModel.get('shares'), 'share_with_displayname')\n\t\t\t// note: we only update the data attribute because updateIcon()\n\t\t\tif (recipients.length) {\n\t\t\t\tvar recipientData = _.mapObject(shareModel.get('shares'), function(share) {\n\t\t\t\t\treturn { shareWith: share.share_with, shareWithDisplayName: share.share_with_displayname }\n\t\t\t\t})\n\t\t\t\t$tr.attr('data-share-recipient-data', JSON.stringify(recipientData))\n\t\t\t} else {\n\t\t\t\t$tr.removeAttr('data-share-recipient-data')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Update the file action share icon for the given file\n\t\t *\n\t\t * @param $tr file element of the file to update\n\t\t * @param {boolean} hasUserShares true if a user share exists\n\t\t * @param {boolean} hasLinkShares true if a link share exists\n\t\t *\n\t\t * @returns {boolean} true if the icon was set, false otherwise\n\t\t */\n\t\t_updateFileActionIcon: function($tr, hasUserShares, hasLinkShares) {\n\t\t\t// if the statuses are loaded already, use them for the icon\n\t\t\t// (needed when scrolling to the next page)\n\t\t\tif (hasUserShares || hasLinkShares || $tr.attr('data-share-recipient-data') || $tr.attr('data-share-owner')) {\n\t\t\t\tOCA.Sharing.Util._markFileAsShared($tr, true, hasLinkShares)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn false\n\t\t},\n\n\t\t/**\n\t\t * Marks/unmarks a given file as shared by changing its action icon\n\t\t * and folder icon.\n\t\t *\n\t\t * @param $tr file element to mark as shared\n\t\t * @param hasShares whether shares are available\n\t\t * @param hasLink whether link share is available\n\t\t */\n\t\t_markFileAsShared: function($tr, hasShares, hasLink) {\n\t\t\tvar action = $tr.find('.fileactions .action[data-action=\"Share\"]')\n\t\t\tvar type = $tr.data('type')\n\t\t\tvar icon = action.find('.icon')\n\t\t\tvar message, recipients, avatars\n\t\t\tvar ownerId = $tr.attr('data-share-owner-id')\n\t\t\tvar owner = $tr.attr('data-share-owner')\n\t\t\tvar mountType = $tr.attr('data-mounttype')\n\t\t\tvar shareFolderIcon\n\t\t\tvar iconClass = 'icon-shared'\n\t\t\taction.removeClass('shared-style')\n\t\t\t// update folder icon\n\t\t\tvar isEncrypted = $tr.attr('data-e2eencrypted')\n\t\t\tif (type === 'dir' && isEncrypted === 'true') {\n\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-encrypted')\n\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t} else if (type === 'dir' && (hasShares || hasLink || ownerId)) {\n\t\t\t\tif (typeof mountType !== 'undefined' && mountType !== 'shared-root' && mountType !== 'shared') {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-' + mountType)\n\t\t\t\t} else if (hasLink) {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-public')\n\t\t\t\t} else {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-shared')\n\t\t\t\t}\n\t\t\t\t$tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')')\n\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t} else if (type === 'dir') {\n\t\t\t\t// FIXME: duplicate of FileList._createRow logic for external folder,\n\t\t\t\t// need to refactor the icon logic into a single code path eventually\n\t\t\t\tif (mountType && mountType.indexOf('external') === 0) {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-external')\n\t\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t\t} else {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir')\n\t\t\t\t\t// back to default\n\t\t\t\t\t$tr.removeAttr('data-icon')\n\t\t\t\t}\n\t\t\t\t$tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')')\n\t\t\t}\n\t\t\t// update share action text / icon\n\t\t\tif (hasShares || ownerId) {\n\t\t\t\trecipients = $tr.data('share-recipient-data')\n\t\t\t\taction.addClass('shared-style')\n\n\t\t\t\tavatars = '<span>' + t('files_sharing', 'Shared') + '</span>'\n\t\t\t\t// even if reshared, only show \"Shared by\"\n\t\t\t\tif (ownerId) {\n\t\t\t\t\tmessage = t('files_sharing', 'Shared by')\n\t\t\t\t\tavatars = OCA.Sharing.Util._formatRemoteShare(ownerId, owner, message)\n\t\t\t\t} else if (recipients) {\n\t\t\t\t\tavatars = OCA.Sharing.Util._formatShareList(recipients)\n\t\t\t\t}\n\t\t\t\taction.html(avatars).prepend(icon)\n\n\t\t\t\tif (ownerId || recipients) {\n\t\t\t\t\tvar avatarElement = action.find('.avatar')\n\t\t\t\t\tavatarElement.each(function() {\n\t\t\t\t\t\t$(this).avatar($(this).data('username'), 32)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\taction.html('<span class=\"hidden-visually\">' + t('files_sharing', 'Shared') + '</span>').prepend(icon)\n\t\t\t}\n\t\t\tif (hasLink) {\n\t\t\t\ticonClass = 'icon-public'\n\t\t\t}\n\t\t\ticon.removeClass('icon-shared icon-public').addClass(iconClass)\n\t\t},\n\t\t/**\n\t\t * Format a remote address\n\t\t *\n\t\t * @param {String} shareWith userid, full remote share, or whatever\n\t\t * @param {String} shareWithDisplayName\n\t\t * @param {String} message\n\t\t * @returns {String} HTML code to display\n\t\t */\n\t\t_formatRemoteShare: function(shareWith, shareWithDisplayName, message) {\n\t\t\tvar parts = OCA.Sharing.Util._REMOTE_OWNER_REGEXP.exec(shareWith)\n\t\t\tif (!parts || !parts[7]) {\n\t\t\t\t// display avatar of the user\n\t\t\t\tvar avatar = '<span class=\"avatar\" data-username=\"' + escapeHTML(shareWith) + '\" title=\"' + message + ' ' + escapeHTML(shareWithDisplayName) + '\"></span>'\n\t\t\t\tvar hidden = '<span class=\"hidden-visually\">' + message + ' ' + escapeHTML(shareWithDisplayName) + '</span> '\n\t\t\t\treturn avatar + hidden\n\t\t\t}\n\n\t\t\tvar userName = parts[2]\n\t\t\tvar userDomain = parts[4]\n\t\t\tvar server = parts[5]\n\t\t\tvar protocol = parts[6]\n\t\t\tvar serverPath = parts[8] ? parts[7] : ''; // no trailing slash on root\n\n\t\t\tvar tooltip = message + ' ' + userName\n\t\t\tif (userDomain) {\n\t\t\t\ttooltip += '@' + userDomain\n\t\t\t}\n\t\t\tif (server) {\n\t\t\t\ttooltip += '@' + server.replace(protocol, '') + serverPath\n\t\t\t}\n\n\t\t\tvar html = '<span class=\"remoteAddress\" title=\"' + escapeHTML(tooltip) + '\">'\n\t\t\thtml += '<span class=\"username\">' + escapeHTML(userName) + '</span>'\n\t\t\tif (userDomain) {\n\t\t\t\thtml += '<span class=\"userDomain\">@' + escapeHTML(userDomain) + '</span>'\n\t\t\t}\n\t\t\thtml += '</span> '\n\t\t\treturn html\n\t\t},\n\t\t/**\n\t\t * Loop over all recipients in the list and format them using\n\t\t * all kind of fancy magic.\n\t\t *\n\t\t* @param {Object} recipients array of all the recipients\n\t\t* @returns {String[]} modified list of recipients\n\t\t*/\n\t\t_formatShareList: function(recipients) {\n\t\t\tvar _parent = this\n\t\t\trecipients = _.toArray(recipients)\n\t\t\trecipients.sort(function(a, b) {\n\t\t\t\treturn a.shareWithDisplayName.localeCompare(b.shareWithDisplayName)\n\t\t\t})\n\t\t\treturn $.map(recipients, function(recipient) {\n\t\t\t\treturn _parent._formatRemoteShare(recipient.shareWith, recipient.shareWithDisplayName, t('files_sharing', 'Shared with'))\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Marks/unmarks a given file as shared by changing its action icon\n\t\t * and folder icon.\n\t\t *\n\t\t* @param $tr file element to mark as shared\n\t\t* @param hasShares whether shares are available\n\t\t* @param hasLink whether link share is available\n\t\t*/\n\t\tmarkFileAsShared: function($tr, hasShares, hasLink) {\n\t\t\tvar action = $tr.find('.fileactions .action[data-action=\"Share\"]')\n\t\t\tvar type = $tr.data('type')\n\t\t\tvar icon = action.find('.icon')\n\t\t\tvar message, recipients, avatars\n\t\t\tvar ownerId = $tr.attr('data-share-owner-id')\n\t\t\tvar owner = $tr.attr('data-share-owner')\n\t\t\tvar mountType = $tr.attr('data-mounttype')\n\t\t\tvar shareFolderIcon\n\t\t\tvar iconClass = 'icon-shared'\n\t\t\taction.removeClass('shared-style')\n\t\t\t// update folder icon\n\t\t\tif (type === 'dir' && (hasShares || hasLink || ownerId)) {\n\t\t\t\tif (typeof mountType !== 'undefined' && mountType !== 'shared-root' && mountType !== 'shared') {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-' + mountType)\n\t\t\t\t} else if (hasLink) {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-public')\n\t\t\t\t} else {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-shared')\n\t\t\t\t}\n\t\t\t\t$tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')')\n\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t} else if (type === 'dir') {\n\t\t\t\tvar isEncrypted = $tr.attr('data-e2eencrypted')\n\t\t\t\t// FIXME: duplicate of FileList._createRow logic for external folder,\n\t\t\t\t// need to refactor the icon logic into a single code path eventually\n\t\t\t\tif (isEncrypted === 'true') {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-encrypted')\n\t\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t\t} else if (mountType && mountType.indexOf('external') === 0) {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-external')\n\t\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t\t} else {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir')\n\t\t\t\t\t// back to default\n\t\t\t\t\t$tr.removeAttr('data-icon')\n\t\t\t\t}\n\t\t\t\t$tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')')\n\t\t\t}\n\t\t\t// update share action text / icon\n\t\t\tif (hasShares || ownerId) {\n\t\t\t\trecipients = $tr.data('share-recipient-data')\n\t\t\t\taction.addClass('shared-style')\n\n\t\t\t\tavatars = '<span>' + t('files_sharing', 'Shared') + '</span>'\n\t\t\t\t// even if reshared, only show \"Shared by\"\n\t\t\t\tif (ownerId) {\n\t\t\t\t\tmessage = t('files_sharing', 'Shared by')\n\t\t\t\t\tavatars = this._formatRemoteShare(ownerId, owner, message)\n\t\t\t\t} else if (recipients) {\n\t\t\t\t\tavatars = this._formatShareList(recipients)\n\t\t\t\t}\n\t\t\t\taction.html(avatars).prepend(icon)\n\n\t\t\t\tif (ownerId || recipients) {\n\t\t\t\t\tvar avatarElement = action.find('.avatar')\n\t\t\t\t\tavatarElement.each(function() {\n\t\t\t\t\t\t$(this).avatar($(this).data('username'), 32)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\taction.html('<span class=\"hidden-visually\">' + t('files_sharing', 'Shared') + '</span>').prepend(icon)\n\t\t\t}\n\t\t\tif (hasLink) {\n\t\t\t\ticonClass = 'icon-public'\n\t\t\t}\n\t\t\ticon.removeClass('icon-shared icon-public').addClass(iconClass)\n\t\t},\n\n\t\t/**\n\t\t * @param {Array} fileData\n\t\t * @returns {String}\n\t\t */\n\t\tgetSharePermissions: function(fileData) {\n\t\t\treturn fileData.sharePermissions\n\t\t}\n\t}\n})()\n\nOC.Plugins.register('OCA.Files.FileList', OCA.Sharing.Util)\n","/**\n * @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>\n *\n * @author Christoph Wurst <christoph@winzerhof-wurst.at>\n * @author John Molakvoæ <skjnldsv@protonmail.com>\n * @author Roeland Jago Douma <roeland@famdouma.nl>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport { Type as ShareTypes } from '@nextcloud/sharing'\n\n(function() {\n\t'use strict'\n\n\tconst BreadCrumbView = OC.Backbone.View.extend({\n\t\ttagName: 'span',\n\t\tevents: {\n\t\t\tclick: '_onClick',\n\t\t},\n\t\t_dirInfo: undefined,\n\n\t\trender(data) {\n\t\t\tthis._dirInfo = data.dirInfo || null\n\n\t\t\tif (this._dirInfo !== null && (this._dirInfo.path !== '/' || this._dirInfo.name !== '')) {\n\t\t\t\tconst isShared = data.dirInfo && data.dirInfo.shareTypes && data.dirInfo.shareTypes.length > 0\n\t\t\t\tthis.$el.removeClass('shared icon-public icon-shared')\n\t\t\t\tif (isShared) {\n\t\t\t\t\tthis.$el.addClass('shared')\n\t\t\t\t\tif (data.dirInfo.shareTypes.indexOf(ShareTypes.SHARE_TYPE_LINK) !== -1) {\n\t\t\t\t\t\tthis.$el.addClass('icon-public')\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.$el.addClass('icon-shared')\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.$el.addClass('icon-shared')\n\t\t\t\t}\n\t\t\t\tthis.$el.show()\n\t\t\t\tthis.delegateEvents()\n\t\t\t} else {\n\t\t\t\tthis.$el.removeClass('shared icon-public icon-shared')\n\t\t\t\tthis.$el.hide()\n\t\t\t}\n\n\t\t\treturn this\n\t\t},\n\t\t_onClick(e) {\n\t\t\te.preventDefault()\n\t\t\te.stopPropagation()\n\n\t\t\tconst fileInfoModel = new OCA.Files.FileInfoModel(this._dirInfo)\n\t\t\tconst self = this\n\t\t\tfileInfoModel.on('change', function() {\n\t\t\t\tself.render({\n\t\t\t\t\tdirInfo: self._dirInfo,\n\t\t\t\t})\n\t\t\t})\n\n\t\t\tconst path = fileInfoModel.attributes.path + '/' + fileInfoModel.attributes.name\n\t\t\tOCA.Files.Sidebar.open(path)\n\t\t\tOCA.Files.Sidebar.setActiveTab('sharing')\n\t\t},\n\t})\n\n\tOCA.Sharing.ShareBreadCrumbView = BreadCrumbView\n})()\n","\n import API from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/sass-loader/dist/cjs.js!./sharebreadcrumb.scss\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/sass-loader/dist/cjs.js!./sharebreadcrumb.scss\";\n export default content && content.locals ? content.locals : undefined;\n","/**\n * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl>\n *\n * @author John Molakvoæ <skjnldsv@protonmail.com>\n * @author Julius Härtl <jus@bitgrid.net>\n * @author Roeland Jago Douma <roeland@famdouma.nl>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport './share.js'\nimport './sharebreadcrumbview.js'\nimport './style/sharebreadcrumb.scss'\nimport './collaborationresourceshandler.js'\n\n// eslint-disable-next-line camelcase\n__webpack_nonce__ = btoa(OC.requestToken)\n\nwindow.OCA.Sharing = OCA.Sharing\n","/**\n * @copyright Copyright (c) 2016 John Molakvoæ <skjnldsv@protonmail.com>\n *\n * @author John Molakvoæ <skjnldsv@protonmail.com>\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\n// eslint-disable-next-line camelcase\n__webpack_nonce__ = btoa(OC.requestToken)\n\nwindow.OCP.Collaboration.registerType('file', {\n\taction: () => {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tOC.dialogs.filepicker(t('files_sharing', 'Link to a file'), function(f) {\n\t\t\t\tconst client = OC.Files.getClient()\n\t\t\t\tclient.getFileInfo(f).then((status, fileInfo) => {\n\t\t\t\t\tresolve(fileInfo.id)\n\t\t\t\t}).fail(() => {\n\t\t\t\t\treject(new Error('Cannot get fileinfo'))\n\t\t\t\t})\n\t\t\t}, false, null, false, OC.dialogs.FILEPICKER_TYPE_CHOOSE, '', { allowDirectoryChooser: true })\n\t\t})\n\t},\n\ttypeString: t('files_sharing', 'Link to a file'),\n\ttypeIconClass: 'icon-files-dark',\n})\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"li.crumb span.icon-shared,li.crumb span.icon-public{display:inline-block;cursor:pointer;opacity:.2;margin-right:6px}li.crumb span.icon-shared.shared,li.crumb span.icon-public.shared{opacity:.7}\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/files_sharing/src/style/sharebreadcrumb.scss\"],\"names\":[],\"mappings\":\"AAsBA,oDAEC,oBAAA,CACA,cAAA,CACA,UAAA,CACA,gBAAA,CAGD,kEAEC,UAAA\",\"sourcesContent\":[\"/**\\n * @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>\\n *\\n * @author 2016 Christoph Wurst <christoph@winzerhof-wurst.at>\\n *\\n * @license GNU AGPL version 3 or any later version\\n *\\n * This program is free software: you can redistribute it and/or modify\\n * it under the terms of the GNU Affero General Public License as\\n * published by the Free Software Foundation, either version 3 of the\\n * License, or (at your option) any later version.\\n *\\n * This program is distributed in the hope that it will be useful,\\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n * GNU Affero General Public License for more details.\\n *\\n * You should have received a copy of the GNU Affero General Public License\\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\\n *\\n */\\n\\nli.crumb span.icon-shared,\\nli.crumb span.icon-public {\\n\\tdisplay: inline-block;\\n\\tcursor: pointer;\\n\\topacity: 0.2;\\n\\tmargin-right: 6px;\\n}\\n\\nli.crumb span.icon-shared.shared,\\nli.crumb span.icon-public.shared {\\n\\topacity: 0.7;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.j = 6200;","__webpack_require__.b = document.baseURI || self.location.href;\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t6200: 0,\n\t5438: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunknextcloud\"] = self[\"webpackChunknextcloud\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.nc = undefined;","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [7874], () => (__webpack_require__(5972)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","_","extend","OC","Files","Client","PROPERTY_SHARE_TYPES","NS_OWNCLOUD","PROPERTY_OWNER_ID","PROPERTY_OWNER_DISPLAY_NAME","OCA","Sharing","Util","_REMOTE_OWNER_REGEXP","RegExp","attach","fileList","_getCapabilities$file","getCapabilities","files_sharing","api_enabled","id","fileActions","oldCreateRow","_createRow","fileData","tr","apply","this","arguments","sharePermissions","getSharePermissions","permissions","actions","all","Comment","Details","Goto","isFunction","canDownload","Download","PERMISSION_UPDATE","MoveCopy","attr","JSON","stringify","shareAttributes","shareOwner","shareOwnerId","mountType","recipientData","isEmpty","shareTypes","join","oldElementToFile","elementToFile","$el","fileInfo","parse","undefined","split","expirationTimestamp","parseInt","shares","push","expiration","oldGetWebdavProperties","_getWebdavProperties","props","filesClient","addFileInfoParser","response","data","propStat","properties","permissionsProp","PROPERTY_PERMISSIONS","indexOf","shareTypesProp","chain","filter","xmlvalue","namespaceURI","nodeName","map","textContent","text","value","on","ev","$files","each","file","$tr","$","shareTypesStr","hasLink","hasShares","shareTypeStr","shareType","ShareTypes","_updateFileActionIcon","sharesLoaded","registerAction","name","displayName","context","$file","t","altText","mime","order","PERMISSION_ALL","iconClass","fileName","icon","generateUrl","concat","type","FileActions","TYPE_INLINE","actionHandler","_detailsView","isNaN","showDetailsView","render","actionSpec","isDefault","PERMISSION_SHARE","_defaultRenderAction","call","breadCrumbSharingDetailView","ShareBreadCrumbView","registerBreadCrumbDetailView","_updateFileListDataAttributes","shareModel","pluck","get","length","mapObject","share","shareWith","share_with","shareWithDisplayName","share_with_displayname","removeAttr","hasUserShares","hasLinkShares","_markFileAsShared","message","recipients","avatars","shareFolderIcon","action","find","ownerId","owner","removeClass","isEncrypted","MimeType","getIconUrl","css","addClass","_formatRemoteShare","_formatShareList","html","prepend","avatar","parts","exec","escapeHTML","userName","userDomain","server","protocol","serverPath","tooltip","replace","_parent","toArray","sort","a","b","localeCompare","recipient","markFileAsShared","Plugins","register","BreadCrumbView","Backbone","View","tagName","events","click","_dirInfo","dirInfo","path","hide","isShared","show","delegateEvents","_onClick","e","preventDefault","stopPropagation","fileInfoModel","FileInfoModel","self","attributes","Sidebar","open","setActiveTab","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","__webpack_nonce__","btoa","requestToken","window","OCP","Collaboration","registerType","Promise","resolve","reject","dialogs","filepicker","f","getClient","getFileInfo","then","status","fail","Error","FILEPICKER_TYPE_CHOOSE","allowDirectoryChooser","typeString","typeIconClass","___CSS_LOADER_EXPORT___","module","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","loaded","__webpack_modules__","m","O","result","chunkIds","fn","priority","notFulfilled","Infinity","i","fulfilled","j","Object","keys","every","key","splice","r","n","getter","__esModule","d","definition","o","defineProperty","enumerable","g","globalThis","Function","obj","prop","prototype","hasOwnProperty","Symbol","toStringTag","nmd","paths","children","document","baseURI","location","href","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","forEach","bind","nc","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file
+{"version":3,"file":"files_sharing-additionalScripts.js?v=4048ce644c9ad516a624","mappings":"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","sources":["webpack:///nextcloud/webpack/runtime/chunk loaded","webpack:///nextcloud/apps/files_sharing/src/share.js","webpack:///nextcloud/apps/files_sharing/src/sharebreadcrumbview.js","webpack://nextcloud/./apps/files_sharing/src/style/sharebreadcrumb.scss?a9a3","webpack:///nextcloud/apps/files_sharing/src/additionalScripts.js","webpack:///nextcloud/apps/files_sharing/src/collaborationresourceshandler.js","webpack:///nextcloud/apps/files_sharing/src/style/sharebreadcrumb.scss","webpack:///nextcloud/webpack/bootstrap","webpack:///nextcloud/webpack/runtime/compat get default export","webpack:///nextcloud/webpack/runtime/define property getters","webpack:///nextcloud/webpack/runtime/global","webpack:///nextcloud/webpack/runtime/hasOwnProperty shorthand","webpack:///nextcloud/webpack/runtime/make namespace object","webpack:///nextcloud/webpack/runtime/node module decorator","webpack:///nextcloud/webpack/runtime/runtimeId","webpack:///nextcloud/webpack/runtime/jsonp chunk loading","webpack:///nextcloud/webpack/runtime/nonce","webpack:///nextcloud/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","/**\n * Copyright (c) 2014\n *\n * @author Arthur Schiwon <blizzz@arthur-schiwon.de>\n * @author Christoph Wurst <christoph@winzerhof-wurst.at>\n * @author Daniel Calviño Sánchez <danxuliu@gmail.com>\n * @author Joas Schilling <coding@schilljs.com>\n * @author John Molakvoæ <skjnldsv@protonmail.com>\n * @author Julius Härtl <jus@bitgrid.net>\n * @author Maxence Lange <maxence@nextcloud.com>\n * @author Michael Jobst <mjobst+github@tecratech.de>\n * @author Michael Jobst <mjobst@necls.com>\n * @author Morris Jobke <hey@morrisjobke.de>\n * @author Roeland Jago Douma <roeland@famdouma.nl>\n * @author Samuel <faust64@gmail.com>\n * @author Vincent Petry <vincent@nextcloud.com>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\n/* eslint-disable */\nimport escapeHTML from 'escape-html'\n\nimport { Type as ShareTypes } from '@nextcloud/sharing'\nimport { getCapabilities } from '@nextcloud/capabilities'\n\n(function() {\n\n\t_.extend(OC.Files.Client, {\n\t\tPROPERTY_SHARE_TYPES:\t'{' + OC.Files.Client.NS_OWNCLOUD + '}share-types',\n\t\tPROPERTY_OWNER_ID:\t'{' + OC.Files.Client.NS_OWNCLOUD + '}owner-id',\n\t\tPROPERTY_OWNER_DISPLAY_NAME:\t'{' + OC.Files.Client.NS_OWNCLOUD + '}owner-display-name'\n\t})\n\n\tif (!OCA.Sharing) {\n\t\tOCA.Sharing = {}\n\t}\n\n\t/**\n\t * @namespace\n\t */\n\tOCA.Sharing.Util = {\n\n\t\t/**\n\t\t * Regular expression for splitting parts of remote share owners:\n\t\t * \"user@example.com/\"\n\t\t * \"user@example.com/path/to/owncloud\"\n\t\t * \"user@anotherexample.com@example.com/path/to/owncloud\n\t\t */\n\t\t_REMOTE_OWNER_REGEXP: new RegExp('^(([^@]*)@(([^@^/\\\\s]*)@)?)((https://)?[^[\\\\s/]*)([/](.*))?$'),\n\n\t\t/**\n\t\t * Initialize the sharing plugin.\n\t\t *\n\t\t * Registers the \"Share\" file action and adds additional\n\t\t * DOM attributes for the sharing file info.\n\t\t *\n\t\t * @param {OCA.Files.FileList} fileList file list to be extended\n\t\t */\n\t\tattach: function(fileList) {\n\t\t\t// core sharing is disabled/not loaded\n\t\t\tif (!getCapabilities().files_sharing?.api_enabled) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (fileList.id === 'trashbin' || fileList.id === 'files.public') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvar fileActions = fileList.fileActions\n\t\t\tvar oldCreateRow = fileList._createRow\n\t\t\tfileList._createRow = function(fileData) {\n\n\t\t\t\tvar tr = oldCreateRow.apply(this, arguments)\n\t\t\t\tvar sharePermissions = OCA.Sharing.Util.getSharePermissions(fileData)\n\n\t\t\t\tif (fileData.permissions === 0) {\n\t\t\t\t\t// no permission, disabling sidebar\n\t\t\t\t\tdelete fileActions.actions.all.Comment\n\t\t\t\t\tdelete fileActions.actions.all.Details\n\t\t\t\t\tdelete fileActions.actions.all.Goto\n\t\t\t\t}\n\t\t\t\tif (_.isFunction(fileData.canDownload) && !fileData.canDownload()) {\n\t\t\t\t\tdelete fileActions.actions.all.Download\n\t\t\t\t\tif ((fileData.permissions & OC.PERMISSION_UPDATE) === 0) {\n\t\t\t\t\t\t// neither move nor copy is allowed, remove the action completely\n\t\t\t\t\t\tdelete fileActions.actions.all.MoveCopy\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttr.attr('data-share-permissions', sharePermissions)\n\t\t\t\ttr.attr('data-share-attributes', JSON.stringify(fileData.shareAttributes))\n\t\t\t\tif (fileData.shareOwner) {\n\t\t\t\t\ttr.attr('data-share-owner', fileData.shareOwner)\n\t\t\t\t\ttr.attr('data-share-owner-id', fileData.shareOwnerId)\n\t\t\t\t\t// user should always be able to rename a mount point\n\t\t\t\t\tif (fileData.mountType === 'shared-root') {\n\t\t\t\t\t\ttr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (fileData.recipientData && !_.isEmpty(fileData.recipientData)) {\n\t\t\t\t\ttr.attr('data-share-recipient-data', JSON.stringify(fileData.recipientData))\n\t\t\t\t}\n\t\t\t\tif (fileData.shareTypes) {\n\t\t\t\t\ttr.attr('data-share-types', fileData.shareTypes.join(','))\n\t\t\t\t}\n\t\t\t\treturn tr\n\t\t\t}\n\n\t\t\tvar oldElementToFile = fileList.elementToFile\n\t\t\tfileList.elementToFile = function($el) {\n\t\t\t\tvar fileInfo = oldElementToFile.apply(this, arguments)\n\t\t\t\tfileInfo.shareAttributes = JSON.parse($el.attr('data-share-attributes') || '[]')\n\t\t\t\tfileInfo.sharePermissions = $el.attr('data-share-permissions') || undefined\n\t\t\t\tfileInfo.shareOwner = $el.attr('data-share-owner') || undefined\n\t\t\t\tfileInfo.shareOwnerId = $el.attr('data-share-owner-id') || undefined\n\n\t\t\t\tif ($el.attr('data-share-types')) {\n\t\t\t\t\tfileInfo.shareTypes = $el.attr('data-share-types').split(',')\n\t\t\t\t}\n\n\t\t\t\tif ($el.attr('data-expiration')) {\n\t\t\t\t\tvar expirationTimestamp = parseInt($el.attr('data-expiration'))\n\t\t\t\t\tfileInfo.shares = []\n\t\t\t\t\tfileInfo.shares.push({ expiration: expirationTimestamp })\n\t\t\t\t}\n\n\t\t\t\treturn fileInfo\n\t\t\t}\n\n\t\t\tvar oldGetWebdavProperties = fileList._getWebdavProperties\n\t\t\tfileList._getWebdavProperties = function() {\n\t\t\t\tvar props = oldGetWebdavProperties.apply(this, arguments)\n\t\t\t\tprops.push(OC.Files.Client.PROPERTY_OWNER_ID)\n\t\t\t\tprops.push(OC.Files.Client.PROPERTY_OWNER_DISPLAY_NAME)\n\t\t\t\tprops.push(OC.Files.Client.PROPERTY_SHARE_TYPES)\n\t\t\t\treturn props\n\t\t\t}\n\n\t\t\tfileList.filesClient.addFileInfoParser(function(response) {\n\t\t\t\tvar data = {}\n\t\t\t\tvar props = response.propStat[0].properties\n\t\t\t\tvar permissionsProp = props[OC.Files.Client.PROPERTY_PERMISSIONS]\n\n\t\t\t\tif (permissionsProp && permissionsProp.indexOf('S') >= 0) {\n\t\t\t\t\tdata.shareOwner = props[OC.Files.Client.PROPERTY_OWNER_DISPLAY_NAME]\n\t\t\t\t\tdata.shareOwnerId = props[OC.Files.Client.PROPERTY_OWNER_ID]\n\t\t\t\t}\n\n\t\t\t\tvar shareTypesProp = props[OC.Files.Client.PROPERTY_SHARE_TYPES]\n\t\t\t\tif (shareTypesProp) {\n\t\t\t\t\tdata.shareTypes = _.chain(shareTypesProp).filter(function(xmlvalue) {\n\t\t\t\t\t\treturn (xmlvalue.namespaceURI === OC.Files.Client.NS_OWNCLOUD && xmlvalue.nodeName.split(':')[1] === 'share-type')\n\t\t\t\t\t}).map(function(xmlvalue) {\n\t\t\t\t\t\treturn parseInt(xmlvalue.textContent || xmlvalue.text, 10)\n\t\t\t\t\t}).value()\n\t\t\t\t}\n\n\t\t\t\treturn data\n\t\t\t})\n\n\t\t\t// use delegate to catch the case with multiple file lists\n\t\t\tfileList.$el.on('fileActionsReady', function(ev) {\n\t\t\t\tvar $files = ev.$files\n\n\t\t\t\t_.each($files, function(file) {\n\t\t\t\t\tvar $tr = $(file)\n\t\t\t\t\tvar shareTypesStr = $tr.attr('data-share-types') || ''\n\t\t\t\t\tvar shareOwner = $tr.attr('data-share-owner')\n\t\t\t\t\tif (shareTypesStr || shareOwner) {\n\t\t\t\t\t\tvar hasLink = false\n\t\t\t\t\t\tvar hasShares = false\n\t\t\t\t\t\t_.each(shareTypesStr.split(',') || [], function(shareTypeStr) {\n\t\t\t\t\t\t\tlet shareType = parseInt(shareTypeStr, 10)\n\t\t\t\t\t\t\tif (shareType === ShareTypes.SHARE_TYPE_LINK) {\n\t\t\t\t\t\t\t\thasLink = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_EMAIL) {\n\t\t\t\t\t\t\t\thasLink = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_USER) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_GROUP) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_REMOTE) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_REMOTE_GROUP) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_CIRCLE) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_ROOM) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_DECK) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t} else if (shareType === ShareTypes.SHARE_TYPE_SCIENCEMESH) {\n\t\t\t\t\t\t\t\thasShares = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\tOCA.Sharing.Util._updateFileActionIcon($tr, hasShares, hasLink)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\n\t\t\tfileList.$el.on('changeDirectory', function() {\n\t\t\t\tOCA.Sharing.sharesLoaded = false\n\t\t\t})\n\n\t\t\tfileActions.registerAction({\n\t\t\t\tname: 'Share',\n\t\t\t\tdisplayName: function(context) {\n\t\t\t\t\tif (context && context.$file) {\n\t\t\t\t\t\tvar shareType = parseInt(context.$file.data('share-types'), 10)\n\t\t\t\t\t\tvar shareOwner = context.$file.data('share-owner-id')\n\t\t\t\t\t\tif (shareType >= 0 || shareOwner) {\n\t\t\t\t\t\t\treturn t('files_sharing', 'Shared')\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn t('files_sharing', 'Share')\n\t\t\t\t},\n\t\t\t\taltText: t('files_sharing', 'Share'),\n\t\t\t\tmime: 'all',\n\t\t\t\torder: -150,\n\t\t\t\tpermissions: OC.PERMISSION_ALL,\n\t\t\t\ticonClass: function(fileName, context) {\n\t\t\t\t\tvar shareType = parseInt(context.$file.data('share-types'), 10)\n\t\t\t\t\tif (shareType === ShareTypes.SHARE_TYPE_EMAIL\n\t\t\t\t\t\t|| shareType === ShareTypes.SHARE_TYPE_LINK) {\n\t\t\t\t\t\treturn 'icon-public'\n\t\t\t\t\t}\n\t\t\t\t\treturn 'icon-shared'\n\t\t\t\t},\n\t\t\t\ticon: function(fileName, context) {\n\t\t\t\t\tvar shareOwner = context.$file.data('share-owner-id')\n\t\t\t\t\tif (shareOwner) {\n\t\t\t\t\t\treturn OC.generateUrl(`/avatar/${shareOwner}/32`)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\ttype: OCA.Files.FileActions.TYPE_INLINE,\n\t\t\t\tactionHandler: function(fileName, context) {\n\t\t\t\t\t// details view disabled in some share lists\n\t\t\t\t\tif (!fileList._detailsView) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// do not open sidebar if permission is set and equal to 0\n\t\t\t\t\tvar permissions = parseInt(context.$file.data('share-permissions'), 10)\n\t\t\t\t\tif (isNaN(permissions) || permissions > 0) {\n\t\t\t\t\t\tfileList.showDetailsView(fileName, 'sharing')\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\trender: function(actionSpec, isDefault, context) {\n\t\t\t\t\tvar permissions = parseInt(context.$file.data('permissions'), 10)\n\t\t\t\t\t// if no share permissions but share owner exists, still show the link\n\t\t\t\t\tif ((permissions & OC.PERMISSION_SHARE) !== 0 || context.$file.attr('data-share-owner')) {\n\t\t\t\t\t\treturn fileActions._defaultRenderAction.call(fileActions, actionSpec, isDefault, context)\n\t\t\t\t\t}\n\t\t\t\t\t// don't render anything\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t})\n\n\t\t\t// register share breadcrumbs component\n\t\t\tvar breadCrumbSharingDetailView = new OCA.Sharing.ShareBreadCrumbView()\n\t\t\tfileList.registerBreadCrumbDetailView(breadCrumbSharingDetailView)\n\t\t},\n\n\t\t/**\n\t\t * Update file list data attributes\n\t\t */\n\t\t_updateFileListDataAttributes: function(fileList, $tr, shareModel) {\n\t\t\t// files app current cannot show recipients on load, so we don't update the\n\t\t\t// icon when changed for consistency\n\t\t\tif (fileList.id === 'files') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvar recipients = _.pluck(shareModel.get('shares'), 'share_with_displayname')\n\t\t\t// note: we only update the data attribute because updateIcon()\n\t\t\tif (recipients.length) {\n\t\t\t\tvar recipientData = _.mapObject(shareModel.get('shares'), function(share) {\n\t\t\t\t\treturn { shareWith: share.share_with, shareWithDisplayName: share.share_with_displayname }\n\t\t\t\t})\n\t\t\t\t$tr.attr('data-share-recipient-data', JSON.stringify(recipientData))\n\t\t\t} else {\n\t\t\t\t$tr.removeAttr('data-share-recipient-data')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Update the file action share icon for the given file\n\t\t *\n\t\t * @param $tr file element of the file to update\n\t\t * @param {boolean} hasUserShares true if a user share exists\n\t\t * @param {boolean} hasLinkShares true if a link share exists\n\t\t *\n\t\t * @returns {boolean} true if the icon was set, false otherwise\n\t\t */\n\t\t_updateFileActionIcon: function($tr, hasUserShares, hasLinkShares) {\n\t\t\t// if the statuses are loaded already, use them for the icon\n\t\t\t// (needed when scrolling to the next page)\n\t\t\tif (hasUserShares || hasLinkShares || $tr.attr('data-share-recipient-data') || $tr.attr('data-share-owner')) {\n\t\t\t\tOCA.Sharing.Util._markFileAsShared($tr, true, hasLinkShares)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn false\n\t\t},\n\n\t\t/**\n\t\t * Marks/unmarks a given file as shared by changing its action icon\n\t\t * and folder icon.\n\t\t *\n\t\t * @param $tr file element to mark as shared\n\t\t * @param hasShares whether shares are available\n\t\t * @param hasLink whether link share is available\n\t\t */\n\t\t_markFileAsShared: function($tr, hasShares, hasLink) {\n\t\t\tvar action = $tr.find('.fileactions .action[data-action=\"Share\"]')\n\t\t\tvar type = $tr.data('type')\n\t\t\tvar icon = action.find('.icon')\n\t\t\tvar message, recipients, avatars\n\t\t\tvar ownerId = $tr.attr('data-share-owner-id')\n\t\t\tvar owner = $tr.attr('data-share-owner')\n\t\t\tvar mountType = $tr.attr('data-mounttype')\n\t\t\tvar shareFolderIcon\n\t\t\tvar iconClass = 'icon-shared'\n\t\t\taction.removeClass('shared-style')\n\t\t\t// update folder icon\n\t\t\tvar isEncrypted = $tr.attr('data-e2eencrypted')\n\t\t\tif (type === 'dir' && isEncrypted === 'true') {\n\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-encrypted')\n\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t} else if (type === 'dir' && (hasShares || hasLink || ownerId)) {\n\t\t\t\tif (typeof mountType !== 'undefined' && mountType !== 'shared-root' && mountType !== 'shared') {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-' + mountType)\n\t\t\t\t} else if (hasLink) {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-public')\n\t\t\t\t} else {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-shared')\n\t\t\t\t}\n\t\t\t\t$tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')')\n\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t} else if (type === 'dir') {\n\t\t\t\t// FIXME: duplicate of FileList._createRow logic for external folder,\n\t\t\t\t// need to refactor the icon logic into a single code path eventually\n\t\t\t\tif (mountType && mountType.indexOf('external') === 0) {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-external')\n\t\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t\t} else {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir')\n\t\t\t\t\t// back to default\n\t\t\t\t\t$tr.removeAttr('data-icon')\n\t\t\t\t}\n\t\t\t\t$tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')')\n\t\t\t}\n\t\t\t// update share action text / icon\n\t\t\tif (hasShares || ownerId) {\n\t\t\t\trecipients = $tr.data('share-recipient-data')\n\t\t\t\taction.addClass('shared-style')\n\n\t\t\t\tavatars = '<span>' + t('files_sharing', 'Shared') + '</span>'\n\t\t\t\t// even if reshared, only show \"Shared by\"\n\t\t\t\tif (ownerId) {\n\t\t\t\t\tmessage = t('files_sharing', 'Shared by')\n\t\t\t\t\tavatars = OCA.Sharing.Util._formatRemoteShare(ownerId, owner, message)\n\t\t\t\t} else if (recipients) {\n\t\t\t\t\tavatars = OCA.Sharing.Util._formatShareList(recipients)\n\t\t\t\t}\n\t\t\t\taction.html(avatars).prepend(icon)\n\n\t\t\t\tif (ownerId || recipients) {\n\t\t\t\t\tvar avatarElement = action.find('.avatar')\n\t\t\t\t\tavatarElement.each(function() {\n\t\t\t\t\t\t$(this).avatar($(this).data('username'), 32)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\taction.html('<span class=\"hidden-visually\">' + t('files_sharing', 'Shared') + '</span>').prepend(icon)\n\t\t\t}\n\t\t\tif (hasLink) {\n\t\t\t\ticonClass = 'icon-public'\n\t\t\t}\n\t\t\ticon.removeClass('icon-shared icon-public').addClass(iconClass)\n\t\t},\n\t\t/**\n\t\t * Format a remote address\n\t\t *\n\t\t * @param {String} shareWith userid, full remote share, or whatever\n\t\t * @param {String} shareWithDisplayName\n\t\t * @param {String} message\n\t\t * @returns {String} HTML code to display\n\t\t */\n\t\t_formatRemoteShare: function(shareWith, shareWithDisplayName, message) {\n\t\t\tvar parts = OCA.Sharing.Util._REMOTE_OWNER_REGEXP.exec(shareWith)\n\t\t\tif (!parts || !parts[7]) {\n\t\t\t\t// display avatar of the user\n\t\t\t\tvar avatar = '<span class=\"avatar\" data-username=\"' + escapeHTML(shareWith) + '\" title=\"' + message + ' ' + escapeHTML(shareWithDisplayName) + '\"></span>'\n\t\t\t\tvar hidden = '<span class=\"hidden-visually\">' + message + ' ' + escapeHTML(shareWithDisplayName) + '</span> '\n\t\t\t\treturn avatar + hidden\n\t\t\t}\n\n\t\t\tvar userName = parts[2]\n\t\t\tvar userDomain = parts[4]\n\t\t\tvar server = parts[5]\n\t\t\tvar protocol = parts[6]\n\t\t\tvar serverPath = parts[8] ? parts[7] : ''; // no trailing slash on root\n\n\t\t\tvar tooltip = message + ' ' + userName\n\t\t\tif (userDomain) {\n\t\t\t\ttooltip += '@' + userDomain\n\t\t\t}\n\t\t\tif (server) {\n\t\t\t\ttooltip += '@' + server.replace(protocol, '') + serverPath\n\t\t\t}\n\n\t\t\tvar html = '<span class=\"remoteAddress\" title=\"' + escapeHTML(tooltip) + '\">'\n\t\t\thtml += '<span class=\"username\">' + escapeHTML(userName) + '</span>'\n\t\t\tif (userDomain) {\n\t\t\t\thtml += '<span class=\"userDomain\">@' + escapeHTML(userDomain) + '</span>'\n\t\t\t}\n\t\t\thtml += '</span> '\n\t\t\treturn html\n\t\t},\n\t\t/**\n\t\t * Loop over all recipients in the list and format them using\n\t\t * all kind of fancy magic.\n\t\t *\n\t\t* @param {Object} recipients array of all the recipients\n\t\t* @returns {String[]} modified list of recipients\n\t\t*/\n\t\t_formatShareList: function(recipients) {\n\t\t\tvar _parent = this\n\t\t\trecipients = _.toArray(recipients)\n\t\t\trecipients.sort(function(a, b) {\n\t\t\t\treturn a.shareWithDisplayName.localeCompare(b.shareWithDisplayName)\n\t\t\t})\n\t\t\treturn $.map(recipients, function(recipient) {\n\t\t\t\treturn _parent._formatRemoteShare(recipient.shareWith, recipient.shareWithDisplayName, t('files_sharing', 'Shared with'))\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Marks/unmarks a given file as shared by changing its action icon\n\t\t * and folder icon.\n\t\t *\n\t\t* @param $tr file element to mark as shared\n\t\t* @param hasShares whether shares are available\n\t\t* @param hasLink whether link share is available\n\t\t*/\n\t\tmarkFileAsShared: function($tr, hasShares, hasLink) {\n\t\t\tvar action = $tr.find('.fileactions .action[data-action=\"Share\"]')\n\t\t\tvar type = $tr.data('type')\n\t\t\tvar icon = action.find('.icon')\n\t\t\tvar message, recipients, avatars\n\t\t\tvar ownerId = $tr.attr('data-share-owner-id')\n\t\t\tvar owner = $tr.attr('data-share-owner')\n\t\t\tvar mountType = $tr.attr('data-mounttype')\n\t\t\tvar shareFolderIcon\n\t\t\tvar iconClass = 'icon-shared'\n\t\t\taction.removeClass('shared-style')\n\t\t\t// update folder icon\n\t\t\tif (type === 'dir' && (hasShares || hasLink || ownerId)) {\n\t\t\t\tif (typeof mountType !== 'undefined' && mountType !== 'shared-root' && mountType !== 'shared') {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-' + mountType)\n\t\t\t\t} else if (hasLink) {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-public')\n\t\t\t\t} else {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-shared')\n\t\t\t\t}\n\t\t\t\t$tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')')\n\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t} else if (type === 'dir') {\n\t\t\t\tvar isEncrypted = $tr.attr('data-e2eencrypted')\n\t\t\t\t// FIXME: duplicate of FileList._createRow logic for external folder,\n\t\t\t\t// need to refactor the icon logic into a single code path eventually\n\t\t\t\tif (isEncrypted === 'true') {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-encrypted')\n\t\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t\t} else if (mountType && mountType.indexOf('external') === 0) {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir-external')\n\t\t\t\t\t$tr.attr('data-icon', shareFolderIcon)\n\t\t\t\t} else {\n\t\t\t\t\tshareFolderIcon = OC.MimeType.getIconUrl('dir')\n\t\t\t\t\t// back to default\n\t\t\t\t\t$tr.removeAttr('data-icon')\n\t\t\t\t}\n\t\t\t\t$tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')')\n\t\t\t}\n\t\t\t// update share action text / icon\n\t\t\tif (hasShares || ownerId) {\n\t\t\t\trecipients = $tr.data('share-recipient-data')\n\t\t\t\taction.addClass('shared-style')\n\n\t\t\t\tavatars = '<span>' + t('files_sharing', 'Shared') + '</span>'\n\t\t\t\t// even if reshared, only show \"Shared by\"\n\t\t\t\tif (ownerId) {\n\t\t\t\t\tmessage = t('files_sharing', 'Shared by')\n\t\t\t\t\tavatars = this._formatRemoteShare(ownerId, owner, message)\n\t\t\t\t} else if (recipients) {\n\t\t\t\t\tavatars = this._formatShareList(recipients)\n\t\t\t\t}\n\t\t\t\taction.html(avatars).prepend(icon)\n\n\t\t\t\tif (ownerId || recipients) {\n\t\t\t\t\tvar avatarElement = action.find('.avatar')\n\t\t\t\t\tavatarElement.each(function() {\n\t\t\t\t\t\t$(this).avatar($(this).data('username'), 32)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\taction.html('<span class=\"hidden-visually\">' + t('files_sharing', 'Shared') + '</span>').prepend(icon)\n\t\t\t}\n\t\t\tif (hasLink) {\n\t\t\t\ticonClass = 'icon-public'\n\t\t\t}\n\t\t\ticon.removeClass('icon-shared icon-public').addClass(iconClass)\n\t\t},\n\n\t\t/**\n\t\t * @param {Array} fileData\n\t\t * @returns {String}\n\t\t */\n\t\tgetSharePermissions: function(fileData) {\n\t\t\treturn fileData.sharePermissions\n\t\t}\n\t}\n})()\n\nOC.Plugins.register('OCA.Files.FileList', OCA.Sharing.Util)\n","/**\n * @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>\n *\n * @author Christoph Wurst <christoph@winzerhof-wurst.at>\n * @author John Molakvoæ <skjnldsv@protonmail.com>\n * @author Roeland Jago Douma <roeland@famdouma.nl>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport { Type as ShareTypes } from '@nextcloud/sharing'\n\n(function() {\n\t'use strict'\n\n\tconst BreadCrumbView = OC.Backbone.View.extend({\n\t\ttagName: 'span',\n\t\tevents: {\n\t\t\tclick: '_onClick',\n\t\t},\n\t\t_dirInfo: undefined,\n\n\t\trender(data) {\n\t\t\tthis._dirInfo = data.dirInfo || null\n\n\t\t\tif (this._dirInfo !== null && (this._dirInfo.path !== '/' || this._dirInfo.name !== '')) {\n\t\t\t\tconst isShared = data.dirInfo && data.dirInfo.shareTypes && data.dirInfo.shareTypes.length > 0\n\t\t\t\tthis.$el.removeClass('shared icon-public icon-shared')\n\t\t\t\tif (isShared) {\n\t\t\t\t\tthis.$el.addClass('shared')\n\t\t\t\t\tif (data.dirInfo.shareTypes.indexOf(ShareTypes.SHARE_TYPE_LINK) !== -1) {\n\t\t\t\t\t\tthis.$el.addClass('icon-public')\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.$el.addClass('icon-shared')\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.$el.addClass('icon-shared')\n\t\t\t\t}\n\t\t\t\tthis.$el.show()\n\t\t\t\tthis.delegateEvents()\n\t\t\t} else {\n\t\t\t\tthis.$el.removeClass('shared icon-public icon-shared')\n\t\t\t\tthis.$el.hide()\n\t\t\t}\n\n\t\t\treturn this\n\t\t},\n\t\t_onClick(e) {\n\t\t\te.preventDefault()\n\t\t\te.stopPropagation()\n\n\t\t\tconst fileInfoModel = new OCA.Files.FileInfoModel(this._dirInfo)\n\t\t\tconst self = this\n\t\t\tfileInfoModel.on('change', function() {\n\t\t\t\tself.render({\n\t\t\t\t\tdirInfo: self._dirInfo,\n\t\t\t\t})\n\t\t\t})\n\n\t\t\tconst path = fileInfoModel.attributes.path + '/' + fileInfoModel.attributes.name\n\t\t\tOCA.Files.Sidebar.open(path)\n\t\t\tOCA.Files.Sidebar.setActiveTab('sharing')\n\t\t},\n\t})\n\n\tOCA.Sharing.ShareBreadCrumbView = BreadCrumbView\n})()\n","\n import API from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/sass-loader/dist/cjs.js!./sharebreadcrumb.scss\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/sass-loader/dist/cjs.js!./sharebreadcrumb.scss\";\n export default content && content.locals ? content.locals : undefined;\n","/**\n * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl>\n *\n * @author John Molakvoæ <skjnldsv@protonmail.com>\n * @author Julius Härtl <jus@bitgrid.net>\n * @author Roeland Jago Douma <roeland@famdouma.nl>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport './share.js'\nimport './sharebreadcrumbview.js'\nimport './style/sharebreadcrumb.scss'\nimport './collaborationresourceshandler.js'\n\n// eslint-disable-next-line camelcase\n__webpack_nonce__ = btoa(OC.requestToken)\n\nwindow.OCA.Sharing = OCA.Sharing\n","/**\n * @copyright Copyright (c) 2016 John Molakvoæ <skjnldsv@protonmail.com>\n *\n * @author John Molakvoæ <skjnldsv@protonmail.com>\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\n// eslint-disable-next-line camelcase\n__webpack_nonce__ = btoa(OC.requestToken)\n\nwindow.OCP.Collaboration.registerType('file', {\n\taction: () => {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tOC.dialogs.filepicker(t('files_sharing', 'Link to a file'), function(f) {\n\t\t\t\tconst client = OC.Files.getClient()\n\t\t\t\tclient.getFileInfo(f).then((status, fileInfo) => {\n\t\t\t\t\tresolve(fileInfo.id)\n\t\t\t\t}).fail(() => {\n\t\t\t\t\treject(new Error('Cannot get fileinfo'))\n\t\t\t\t})\n\t\t\t}, false, null, false, OC.dialogs.FILEPICKER_TYPE_CHOOSE, '', { allowDirectoryChooser: true })\n\t\t})\n\t},\n\ttypeString: t('files_sharing', 'Link to a file'),\n\ttypeIconClass: 'icon-files-dark',\n})\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"li.crumb span.icon-shared,li.crumb span.icon-public{display:inline-block;cursor:pointer;opacity:.2;margin-right:6px}li.crumb span.icon-shared.shared,li.crumb span.icon-public.shared{opacity:.7}\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/files_sharing/src/style/sharebreadcrumb.scss\"],\"names\":[],\"mappings\":\"AAsBA,oDAEC,oBAAA,CACA,cAAA,CACA,UAAA,CACA,gBAAA,CAGD,kEAEC,UAAA\",\"sourcesContent\":[\"/**\\n * @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>\\n *\\n * @author 2016 Christoph Wurst <christoph@winzerhof-wurst.at>\\n *\\n * @license GNU AGPL version 3 or any later version\\n *\\n * This program is free software: you can redistribute it and/or modify\\n * it under the terms of the GNU Affero General Public License as\\n * published by the Free Software Foundation, either version 3 of the\\n * License, or (at your option) any later version.\\n *\\n * This program is distributed in the hope that it will be useful,\\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n * GNU Affero General Public License for more details.\\n *\\n * You should have received a copy of the GNU Affero General Public License\\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\\n *\\n */\\n\\nli.crumb span.icon-shared,\\nli.crumb span.icon-public {\\n\\tdisplay: inline-block;\\n\\tcursor: pointer;\\n\\topacity: 0.2;\\n\\tmargin-right: 6px;\\n}\\n\\nli.crumb span.icon-shared.shared,\\nli.crumb span.icon-public.shared {\\n\\topacity: 0.7;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.j = 6200;","__webpack_require__.b = document.baseURI || self.location.href;\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t6200: 0,\n\t5438: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunknextcloud\"] = self[\"webpackChunknextcloud\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.nc = undefined;","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [7874], () => (__webpack_require__(5972)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","_","extend","OC","Files","Client","PROPERTY_SHARE_TYPES","NS_OWNCLOUD","PROPERTY_OWNER_ID","PROPERTY_OWNER_DISPLAY_NAME","OCA","Sharing","Util","_REMOTE_OWNER_REGEXP","RegExp","attach","fileList","_getCapabilities$file","getCapabilities","files_sharing","api_enabled","id","fileActions","oldCreateRow","_createRow","fileData","tr","apply","this","arguments","sharePermissions","getSharePermissions","permissions","actions","all","Comment","Details","Goto","isFunction","canDownload","Download","PERMISSION_UPDATE","MoveCopy","attr","JSON","stringify","shareAttributes","shareOwner","shareOwnerId","mountType","recipientData","isEmpty","shareTypes","join","oldElementToFile","elementToFile","$el","fileInfo","parse","undefined","split","expirationTimestamp","parseInt","shares","push","expiration","oldGetWebdavProperties","_getWebdavProperties","props","filesClient","addFileInfoParser","response","data","propStat","properties","permissionsProp","PROPERTY_PERMISSIONS","indexOf","shareTypesProp","chain","filter","xmlvalue","namespaceURI","nodeName","map","textContent","text","value","on","ev","$files","each","file","$tr","$","shareTypesStr","hasLink","hasShares","shareTypeStr","shareType","ShareTypes","_updateFileActionIcon","sharesLoaded","registerAction","name","displayName","context","$file","t","altText","mime","order","PERMISSION_ALL","iconClass","fileName","icon","generateUrl","concat","type","FileActions","TYPE_INLINE","actionHandler","_detailsView","isNaN","showDetailsView","render","actionSpec","isDefault","PERMISSION_SHARE","_defaultRenderAction","call","breadCrumbSharingDetailView","ShareBreadCrumbView","registerBreadCrumbDetailView","_updateFileListDataAttributes","shareModel","pluck","get","length","mapObject","share","shareWith","share_with","shareWithDisplayName","share_with_displayname","removeAttr","hasUserShares","hasLinkShares","_markFileAsShared","message","recipients","avatars","shareFolderIcon","action","find","ownerId","owner","removeClass","isEncrypted","MimeType","getIconUrl","css","addClass","_formatRemoteShare","_formatShareList","html","prepend","avatar","parts","exec","escapeHTML","userName","userDomain","server","protocol","serverPath","tooltip","replace","_parent","toArray","sort","a","b","localeCompare","recipient","markFileAsShared","Plugins","register","BreadCrumbView","Backbone","View","tagName","events","click","_dirInfo","dirInfo","path","hide","isShared","show","delegateEvents","_onClick","e","preventDefault","stopPropagation","fileInfoModel","FileInfoModel","self","attributes","Sidebar","open","setActiveTab","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","__webpack_nonce__","btoa","requestToken","window","OCP","Collaboration","registerType","Promise","resolve","reject","dialogs","filepicker","f","getClient","getFileInfo","then","status","fail","Error","FILEPICKER_TYPE_CHOOSE","allowDirectoryChooser","typeString","typeIconClass","___CSS_LOADER_EXPORT___","module","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","loaded","__webpack_modules__","m","O","result","chunkIds","fn","priority","notFulfilled","Infinity","i","fulfilled","j","Object","keys","every","key","splice","r","n","getter","__esModule","d","definition","o","defineProperty","enumerable","g","globalThis","Function","obj","prop","prototype","hasOwnProperty","Symbol","toStringTag","nmd","paths","children","document","baseURI","location","href","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","forEach","bind","nc","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 0ef53c1342a..316b21e8122 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -412,6 +412,7 @@ return array(
'OCP\\Group\\Backend\\IIsAdminBackend' => $baseDir . '/lib/public/Group/Backend/IIsAdminBackend.php',
'OCP\\Group\\Backend\\INamedBackend' => $baseDir . '/lib/public/Group/Backend/INamedBackend.php',
'OCP\\Group\\Backend\\IRemoveFromGroupBackend' => $baseDir . '/lib/public/Group/Backend/IRemoveFromGroupBackend.php',
+ 'OCP\\Group\\Backend\\ISearchableGroupBackend' => $baseDir . '/lib/public/Group/Backend/ISearchableGroupBackend.php',
'OCP\\Group\\Backend\\ISetDisplayNameBackend' => $baseDir . '/lib/public/Group/Backend/ISetDisplayNameBackend.php',
'OCP\\Group\\Events\\BeforeGroupChangedEvent' => $baseDir . '/lib/public/Group/Events/BeforeGroupChangedEvent.php',
'OCP\\Group\\Events\\BeforeGroupCreatedEvent' => $baseDir . '/lib/public/Group/Events/BeforeGroupCreatedEvent.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index f1555732936..656f8196320 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -445,6 +445,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Group\\Backend\\IIsAdminBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IIsAdminBackend.php',
'OCP\\Group\\Backend\\INamedBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/INamedBackend.php',
'OCP\\Group\\Backend\\IRemoveFromGroupBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IRemoveFromGroupBackend.php',
+ 'OCP\\Group\\Backend\\ISearchableGroupBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ISearchableGroupBackend.php',
'OCP\\Group\\Backend\\ISetDisplayNameBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ISetDisplayNameBackend.php',
'OCP\\Group\\Events\\BeforeGroupChangedEvent' => __DIR__ . '/../../..' . '/lib/public/Group/Events/BeforeGroupChangedEvent.php',
'OCP\\Group\\Events\\BeforeGroupCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Group/Events/BeforeGroupCreatedEvent.php',
diff --git a/lib/private/Comments/Manager.php b/lib/private/Comments/Manager.php
index c5fb4ebfe34..117318fb278 100644
--- a/lib/private/Comments/Manager.php
+++ b/lib/private/Comments/Manager.php
@@ -1351,7 +1351,8 @@ class Manager implements ICommentsManager {
->set('creation_timestamp', $qb->createNamedParameter($comment->getCreationDateTime(), 'datetime'))
->set('latest_child_timestamp', $qb->createNamedParameter($comment->getLatestChildDateTime(), 'datetime'))
->set('object_type', $qb->createNamedParameter($comment->getObjectType()))
- ->set('object_id', $qb->createNamedParameter($comment->getObjectId()));
+ ->set('object_id', $qb->createNamedParameter($comment->getObjectId()))
+ ->set('expire_date', $qb->createNamedParameter($comment->getExpireDate(), 'datetime'));
if ($tryWritingReferenceId) {
$qb->set('reference_id', $qb->createNamedParameter($comment->getReferenceId()));
diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php
index c50fa1f9de9..2eab4c58a0c 100644
--- a/lib/private/Files/Filesystem.php
+++ b/lib/private/Files/Filesystem.php
@@ -554,7 +554,7 @@ class Filesystem {
}
/**
- * @return string
+ * @return string|false
*/
public static function file_get_contents($path) {
return self::$defaultInstance->file_get_contents($path);
diff --git a/lib/private/Files/Node/File.php b/lib/private/Files/Node/File.php
index 27056efef72..b6cd6571651 100644
--- a/lib/private/Files/Node/File.php
+++ b/lib/private/Files/Node/File.php
@@ -46,14 +46,16 @@ class File extends Node implements \OCP\Files\File {
/**
* @return string
* @throws NotPermittedException
+ * @throws GenericFileException
* @throws LockedException
*/
public function getContent() {
if ($this->checkPermissions(\OCP\Constants::PERMISSION_READ)) {
- /**
- * @var \OC\Files\Storage\Storage $storage;
- */
- return $this->view->file_get_contents($this->path);
+ $content = $this->view->file_get_contents($this->path);
+ if ($content === false) {
+ throw new GenericFileException();
+ }
+ return $content;
} else {
throw new NotPermittedException();
}
@@ -62,7 +64,7 @@ class File extends Node implements \OCP\Files\File {
/**
* @param string|resource $data
* @throws NotPermittedException
- * @throws \OCP\Files\GenericFileException
+ * @throws GenericFileException
* @throws LockedException
*/
public function putContent($data) {
diff --git a/lib/private/Files/Storage/Wrapper/Encoding.php b/lib/private/Files/Storage/Wrapper/Encoding.php
index dd699993e84..6633cbf41e3 100644
--- a/lib/private/Files/Storage/Wrapper/Encoding.php
+++ b/lib/private/Files/Storage/Wrapper/Encoding.php
@@ -300,7 +300,7 @@ class Encoding extends Wrapper {
* see https://www.php.net/manual/en/function.file_get_contents.php
*
* @param string $path
- * @return string|bool
+ * @return string|false
*/
public function file_get_contents($path) {
return $this->storage->file_get_contents($this->findPathToUse($path));
diff --git a/lib/private/Files/Storage/Wrapper/Encryption.php b/lib/private/Files/Storage/Wrapper/Encryption.php
index 720111793de..9c0e6c91463 100644
--- a/lib/private/Files/Storage/Wrapper/Encryption.php
+++ b/lib/private/Files/Storage/Wrapper/Encryption.php
@@ -217,7 +217,7 @@ class Encryption extends Wrapper {
* see https://www.php.net/manual/en/function.file_get_contents.php
*
* @param string $path
- * @return string
+ * @return string|false
*/
public function file_get_contents($path) {
$encryptionModule = $this->getEncryptionModule($path);
diff --git a/lib/private/Files/Storage/Wrapper/Jail.php b/lib/private/Files/Storage/Wrapper/Jail.php
index 619d8b07137..caf039d4cca 100644
--- a/lib/private/Files/Storage/Wrapper/Jail.php
+++ b/lib/private/Files/Storage/Wrapper/Jail.php
@@ -248,7 +248,7 @@ class Jail extends Wrapper {
* see https://www.php.net/manual/en/function.file_get_contents.php
*
* @param string $path
- * @return string|bool
+ * @return string|false
*/
public function file_get_contents($path) {
return $this->getWrapperStorage()->file_get_contents($this->getUnjailedPath($path));
diff --git a/lib/private/Files/Storage/Wrapper/Wrapper.php b/lib/private/Files/Storage/Wrapper/Wrapper.php
index 28a1e0b1e4d..9f5564b4490 100644
--- a/lib/private/Files/Storage/Wrapper/Wrapper.php
+++ b/lib/private/Files/Storage/Wrapper/Wrapper.php
@@ -238,7 +238,7 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStrea
* see https://www.php.net/manual/en/function.file_get_contents.php
*
* @param string $path
- * @return string|bool
+ * @return string|false
*/
public function file_get_contents($path) {
return $this->getWrapperStorage()->file_get_contents($path);
diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php
index 66fe6efb6a5..a73b60989fd 100644
--- a/lib/private/Files/View.php
+++ b/lib/private/Files/View.php
@@ -564,7 +564,7 @@ class View {
/**
* @param string $path
- * @return mixed
+ * @return string|false
* @throws LockedException
*/
public function file_get_contents($path) {
diff --git a/lib/private/Group/Backend.php b/lib/private/Group/Backend.php
index 037cdacf445..1e3e5ef1164 100644
--- a/lib/private/Group/Backend.php
+++ b/lib/private/Group/Backend.php
@@ -126,7 +126,7 @@ abstract class Backend implements \OCP\GroupInterface {
* @param string $search
* @param int $limit
* @param int $offset
- * @return array an array of user ids
+ * @return array<int,string> an array of user ids
*/
public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
return [];
diff --git a/lib/private/Group/Database.php b/lib/private/Group/Database.php
index 5f17477db77..569cfa5007f 100644
--- a/lib/private/Group/Database.php
+++ b/lib/private/Group/Database.php
@@ -40,9 +40,12 @@ use OCP\Group\Backend\IDeleteGroupBackend;
use OCP\Group\Backend\IGetDisplayNameBackend;
use OCP\Group\Backend\IGroupDetailsBackend;
use OCP\Group\Backend\IRemoveFromGroupBackend;
+use OCP\Group\Backend\ISearchableGroupBackend;
use OCP\Group\Backend\ISetDisplayNameBackend;
use OCP\Group\Backend\INamedBackend;
use OCP\IDBConnection;
+use OCP\IUserManager;
+use OC\User\LazyUser;
/**
* Class for group management in a SQL Database (e.g. MySQL, SQLite)
@@ -57,6 +60,7 @@ class Database extends ABackend implements
IGroupDetailsBackend,
IRemoveFromGroupBackend,
ISetDisplayNameBackend,
+ ISearchableGroupBackend,
INamedBackend {
/** @var string[] */
private $groupCache = [];
@@ -324,29 +328,35 @@ class Database extends ABackend implements
}
/**
- * get a list of all users in a group
+ * Get a list of all users in a group
* @param string $gid
* @param string $search
* @param int $limit
* @param int $offset
- * @return array an array of user ids
+ * @return array<int,string> an array of user ids
*/
- public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
+ public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0): array {
+ return array_values(array_map(fn ($user) => $user->getUid(), $this->searchInGroup($gid, $search, $limit, $offset)));
+ }
+
+ public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array {
$this->fixDI();
$query = $this->dbConn->getQueryBuilder();
- $query->select('g.uid')
- ->from('group_user', 'g')
+ $query->select('g.uid', 'u.displayname');
+
+ $query->from('group_user', 'g')
->where($query->expr()->eq('gid', $query->createNamedParameter($gid)))
->orderBy('g.uid', 'ASC');
+ $query->leftJoin('g', 'users', 'u', $query->expr()->eq('g.uid', 'u.uid'));
+
if ($search !== '') {
- $query->leftJoin('g', 'users', 'u', $query->expr()->eq('g.uid', 'u.uid'))
- ->leftJoin('u', 'preferences', 'p', $query->expr()->andX(
- $query->expr()->eq('p.userid', 'u.uid'),
- $query->expr()->eq('p.appid', $query->expr()->literal('settings')),
- $query->expr()->eq('p.configkey', $query->expr()->literal('email')))
- )
+ $query->leftJoin('u', 'preferences', 'p', $query->expr()->andX(
+ $query->expr()->eq('p.userid', 'u.uid'),
+ $query->expr()->eq('p.appid', $query->expr()->literal('settings')),
+ $query->expr()->eq('p.configkey', $query->expr()->literal('email'))
+ ))
// sqlite doesn't like re-using a single named parameter here
->andWhere(
$query->expr()->orX(
@@ -365,11 +375,12 @@ class Database extends ABackend implements
$query->setFirstResult($offset);
}
- $result = $query->execute();
+ $result = $query->executeQuery();
$users = [];
+ $userManager = \OCP\Server::get(IUserManager::class);
while ($row = $result->fetch()) {
- $users[] = $row['uid'];
+ $users[$row['uid']] = new LazyUser($row['uid'], $userManager, $row['displayname'] ?? null);
}
$result->closeCursor();
diff --git a/lib/private/Group/Group.php b/lib/private/Group/Group.php
index cca179bfe19..efc21ad7c0d 100644
--- a/lib/private/Group/Group.php
+++ b/lib/private/Group/Group.php
@@ -33,14 +33,16 @@
namespace OC\Group;
use OC\Hooks\PublicEmitter;
+use OC\User\LazyUser;
+use OCP\GroupInterface;
use OCP\Group\Backend\ICountDisabledInGroup;
use OCP\Group\Backend\IGetDisplayNameBackend;
use OCP\Group\Backend\IHideFromCollaborationBackend;
use OCP\Group\Backend\INamedBackend;
+use OCP\Group\Backend\ISearchableGroupBackend;
use OCP\Group\Backend\ISetDisplayNameBackend;
use OCP\Group\Events\BeforeGroupChangedEvent;
use OCP\Group\Events\GroupChangedEvent;
-use OCP\GroupInterface;
use OCP\IGroup;
use OCP\IUser;
use OCP\IUserManager;
@@ -242,18 +244,23 @@ class Group implements IGroup {
}
/**
- * search for users in the group by userid
- *
- * @param string $search
- * @param int $limit
- * @param int $offset
- * @return \OC\User\User[]
+ * Search for users in the group by userid or display name
+ * @return IUser[]
*/
- public function searchUsers($search, $limit = null, $offset = null) {
+ public function searchUsers(string $search, ?int $limit = null, ?int $offset = null): array {
$users = [];
foreach ($this->backends as $backend) {
- $userIds = $backend->usersInGroup($this->gid, $search, $limit, $offset);
- $users += $this->getVerifiedUsers($userIds);
+ if ($backend instanceof ISearchableGroupBackend) {
+ $users += $backend->searchInGroup($this->gid, $search, $limit ?? -1, $offset ?? 0);
+ } else {
+ $userIds = $backend->usersInGroup($this->gid, $search, $limit ?? -1, $offset ?? 0);
+ $userManager = \OCP\Server::get(IUserManager::class);
+ foreach ($userIds as $userId) {
+ if (!isset($users[$userId])) {
+ $users[$userId] = new LazyUser($userId, $userManager);
+ }
+ }
+ }
if (!is_null($limit) and $limit <= 0) {
return $users;
}
@@ -308,18 +315,11 @@ class Group implements IGroup {
* @param string $search
* @param int $limit
* @param int $offset
- * @return \OC\User\User[]
+ * @return IUser[]
+ * @deprecated 27.0.0 Use searchUsers instead (same implementation)
*/
public function searchDisplayName($search, $limit = null, $offset = null) {
- $users = [];
- foreach ($this->backends as $backend) {
- $userIds = $backend->usersInGroup($this->gid, $search, $limit, $offset);
- $users = $this->getVerifiedUsers($userIds);
- if (!is_null($limit) and $limit <= 0) {
- return array_values($users);
- }
- }
- return array_values($users);
+ return $this->searchUsers($search, $limit, $offset);
}
/**
@@ -375,10 +375,7 @@ class Group implements IGroup {
* @param string[] $userIds an array containing user IDs
* @return \OC\User\User[] an Array with the userId as Key and \OC\User\User as value
*/
- private function getVerifiedUsers($userIds) {
- if (!is_array($userIds)) {
- return [];
- }
+ private function getVerifiedUsers(array $userIds): array {
$users = [];
foreach ($userIds as $userId) {
$user = $this->userManager->get($userId);
diff --git a/lib/private/User/LazyUser.php b/lib/private/User/LazyUser.php
index 096578b8f37..5472cf6f2b4 100644
--- a/lib/private/User/LazyUser.php
+++ b/lib/private/User/LazyUser.php
@@ -30,16 +30,26 @@ use OCP\UserInterface;
class LazyUser implements IUser {
private ?IUser $user = null;
private string $uid;
+ private ?string $displayName;
private IUserManager $userManager;
+ private ?UserInterface $backend;
- public function __construct(string $uid, IUserManager $userManager) {
+ public function __construct(string $uid, IUserManager $userManager, ?string $displayName = null, ?UserInterface $backend = null) {
$this->uid = $uid;
$this->userManager = $userManager;
+ $this->displayName = $displayName;
+ $this->backend = $backend;
}
private function getUser(): IUser {
if ($this->user === null) {
- $this->user = $this->userManager->get($this->uid);
+ if ($this->backend) {
+ /** @var \OC\User\Manager $manager */
+ $manager = $this->userManager;
+ $this->user = $manager->getUserObject($this->uid, $this->backend);
+ } else {
+ $this->user = $this->userManager->get($this->uid);
+ }
}
/** @var IUser */
$user = $this->user;
@@ -51,6 +61,10 @@ class LazyUser implements IUser {
}
public function getDisplayName() {
+ if ($this->displayName) {
+ return $this->displayName;
+ }
+
return $this->userManager->getDisplayName($this->uid) ?? $this->uid;
}
diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php
index 859ebd2a604..60059d5badd 100644
--- a/lib/private/User/Manager.php
+++ b/lib/private/User/Manager.php
@@ -202,7 +202,7 @@ class Manager extends PublicEmitter implements IUserManager {
* @param bool $cacheUser If false the newly created user object will not be cached
* @return \OC\User\User
*/
- protected function getUserObject($uid, $backend, $cacheUser = true) {
+ public function getUserObject($uid, $backend, $cacheUser = true) {
if ($backend instanceof IGetRealUIDBackend) {
$uid = $backend->getRealUID($uid);
}
@@ -293,12 +293,13 @@ class Manager extends PublicEmitter implements IUserManager {
}
/**
- * search by user id
+ * Search by user id
*
* @param string $pattern
* @param int $limit
* @param int $offset
- * @return \OC\User\User[]
+ * @return IUser[]
+ * @deprecated since 27.0.0, use searchDisplayName instead
*/
public function search($pattern, $limit = null, $offset = null) {
$users = [];
@@ -306,28 +307,24 @@ class Manager extends PublicEmitter implements IUserManager {
$backendUsers = $backend->getUsers($pattern, $limit, $offset);
if (is_array($backendUsers)) {
foreach ($backendUsers as $uid) {
- $users[$uid] = $this->getUserObject($uid, $backend);
+ $users[$uid] = new LazyUser($uid, $this, null, $backend);
}
}
}
- uasort($users, function ($a, $b) {
- /**
- * @var \OC\User\User $a
- * @var \OC\User\User $b
- */
+ uasort($users, function (IUser $a, IUser $b) {
return strcasecmp($a->getUID(), $b->getUID());
});
return $users;
}
/**
- * search by displayName
+ * Search by displayName
*
* @param string $pattern
* @param int $limit
* @param int $offset
- * @return \OC\User\User[]
+ * @return IUser[]
*/
public function searchDisplayName($pattern, $limit = null, $offset = null) {
$users = [];
@@ -335,16 +332,12 @@ class Manager extends PublicEmitter implements IUserManager {
$backendUsers = $backend->getDisplayNames($pattern, $limit, $offset);
if (is_array($backendUsers)) {
foreach ($backendUsers as $uid => $displayName) {
- $users[] = $this->getUserObject($uid, $backend);
+ $users[] = new LazyUser($uid, $this, $displayName, $backend);
}
}
}
- usort($users, function ($a, $b) {
- /**
- * @var \OC\User\User $a
- * @var \OC\User\User $b
- */
+ usort($users, function (IUser $a, IUser $b) {
return strcasecmp($a->getDisplayName(), $b->getDisplayName());
});
return $users;
diff --git a/lib/public/Files/File.php b/lib/public/Files/File.php
index 93d0ab860c1..7c1e36cb3eb 100644
--- a/lib/public/Files/File.php
+++ b/lib/public/Files/File.php
@@ -40,6 +40,7 @@ interface File extends Node {
*
* @return string
* @throws NotPermittedException
+ * @throws GenericFileException
* @throws LockedException
* @since 6.0.0
*/
diff --git a/lib/public/Files/Storage.php b/lib/public/Files/Storage.php
index c165266a1b7..31405a26bfa 100644
--- a/lib/public/Files/Storage.php
+++ b/lib/public/Files/Storage.php
@@ -217,7 +217,7 @@ interface Storage extends IStorage {
* see https://www.php.net/manual/en/function.file_get_contents.php
*
* @param string $path
- * @return string|bool
+ * @return string|false
* @since 6.0.0
*/
public function file_get_contents($path);
diff --git a/lib/public/Files/Storage/IStorage.php b/lib/public/Files/Storage/IStorage.php
index 2f38165830b..00e98fdfbb6 100644
--- a/lib/public/Files/Storage/IStorage.php
+++ b/lib/public/Files/Storage/IStorage.php
@@ -214,7 +214,7 @@ interface IStorage {
* see https://www.php.net/manual/en/function.file_get_contents.php
*
* @param string $path
- * @return string|bool
+ * @return string|false
* @since 9.0.0
*/
public function file_get_contents($path);
diff --git a/lib/public/Group/Backend/ISearchableGroupBackend.php b/lib/public/Group/Backend/ISearchableGroupBackend.php
new file mode 100644
index 00000000000..20753822258
--- /dev/null
+++ b/lib/public/Group/Backend/ISearchableGroupBackend.php
@@ -0,0 +1,51 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright (c) 2022 Carl Schwan <carl@carlschwan.eu>
+ *
+ * @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 OCP\Group\Backend;
+
+use OCP\IUser;
+
+/**
+ * @since 27.0.0
+ */
+interface ISearchableGroupBackend {
+ /**
+ * @brief Get a list of users matching the given search parameters.
+ *
+ * Implementations of this method should return lazy evaluated user objects and
+ * preload if possible the display name.
+ *
+ * <code>
+ * $users = $groupBackend->searchInGroup('admin', 'John', 10, 0);
+ * </code>
+ *
+ * @param string $gid The group id of the user we want to search
+ * @param string $search The part of the display name or user id of the users we
+ * want to search. This can be empty to get all the users.
+ * @param int $limit The limit of results
+ * @param int $offset The offset of the results
+ * @return array<string,IUser> Users indexed by uid
+ * @since 27.0.0
+ */
+ public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array;
+}
diff --git a/lib/public/GroupInterface.php b/lib/public/GroupInterface.php
index b7c07136126..56863100c05 100644
--- a/lib/public/GroupInterface.php
+++ b/lib/public/GroupInterface.php
@@ -106,13 +106,15 @@ interface GroupInterface {
public function groupExists($gid);
/**
- * get a list of all users in a group
+ * @brief Get a list of user ids in a group matching the given search parameters.
+ *
* @param string $gid
* @param string $search
* @param int $limit
* @param int $offset
- * @return array an array of user ids
+ * @return array<int,string> an array of user ids
* @since 4.5.0
+ * @deprecated 27.0.0 Use searchInGroup instead, for performance reasons
*/
public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0);
}
diff --git a/lib/public/IGroup.php b/lib/public/IGroup.php
index ba13359c472..ec26cc55b69 100644
--- a/lib/public/IGroup.php
+++ b/lib/public/IGroup.php
@@ -99,7 +99,7 @@ interface IGroup {
* @return \OCP\IUser[]
* @since 8.0.0
*/
- public function searchUsers($search, $limit = null, $offset = null);
+ public function searchUsers(string $search, ?int $limit = null, ?int $offset = null): array;
/**
* returns the number of users matching the search string
diff --git a/tests/lib/Comments/ManagerTest.php b/tests/lib/Comments/ManagerTest.php
index bc1692a5958..5fa1beee374 100644
--- a/tests/lib/Comments/ManagerTest.php
+++ b/tests/lib/Comments/ManagerTest.php
@@ -516,15 +516,41 @@ class ManagerTest extends TestCase {
->setActor('users', 'alice')
->setObject('files', 'file64')
->setMessage('very beautiful, I am impressed!')
- ->setVerb('comment');
+ ->setVerb('comment')
+ ->setExpireDate(new \DateTime('+2 hours'));
$manager->save($comment);
- $comment->setMessage('very beautiful, I am really so much impressed!');
+ $loadedComment = $manager->get($comment->getId());
+ // Compare current object with database values
+ $this->assertSame($comment->getMessage(), $loadedComment->getMessage());
+ $this->assertSame(
+ $comment->getExpireDate()->format('Y-m-d H:i:s'),
+ $loadedComment->getExpireDate()->format('Y-m-d H:i:s')
+ );
+
+ // Preserve the original comment to compare after update
+ $original = clone $comment;
+
+ // Update values
+ $comment->setMessage('very beautiful, I am really so much impressed!')
+ ->setExpireDate(new \DateTime('+1 hours'));
$manager->save($comment);
$loadedComment = $manager->get($comment->getId());
+ // Compare current object with database values
$this->assertSame($comment->getMessage(), $loadedComment->getMessage());
+ $this->assertSame(
+ $comment->getExpireDate()->format('Y-m-d H:i:s'),
+ $loadedComment->getExpireDate()->format('Y-m-d H:i:s')
+ );
+
+ // Compare original object with database values
+ $this->assertNotSame($original->getMessage(), $loadedComment->getMessage());
+ $this->assertNotSame(
+ $original->getExpireDate()->format('Y-m-d H:i:s'),
+ $loadedComment->getExpireDate()->format('Y-m-d H:i:s')
+ );
}
diff --git a/tests/lib/Group/GroupTest.php b/tests/lib/Group/GroupTest.php
index 60f15a65732..ac648fd7b4b 100644
--- a/tests/lib/Group/GroupTest.php
+++ b/tests/lib/Group/GroupTest.php
@@ -303,14 +303,14 @@ class GroupTest extends \Test\TestCase {
$group = new \OC\Group\Group('group1', [$backend], $this->dispatcher, $userManager);
$backend->expects($this->once())
- ->method('usersInGroup')
+ ->method('searchInGroup')
->with('group1', '2')
- ->willReturn(['user2']);
+ ->willReturn(['user2' => new \OC\User\User('user2', null, $this->dispatcher)]);
$users = $group->searchUsers('2');
$this->assertEquals(1, count($users));
- $user2 = $users['user2'];
+ $user2 = reset($users);
$this->assertEquals('user2', $user2->getUID());
}
@@ -325,18 +325,18 @@ class GroupTest extends \Test\TestCase {
$group = new \OC\Group\Group('group1', [$backend1, $backend2], $this->dispatcher, $userManager);
$backend1->expects($this->once())
- ->method('usersInGroup')
+ ->method('searchInGroup')
->with('group1', '2')
- ->willReturn(['user2']);
+ ->willReturn(['user2' => new \OC\User\User('user2', null, $this->dispatcher)]);
$backend2->expects($this->once())
- ->method('usersInGroup')
+ ->method('searchInGroup')
->with('group1', '2')
- ->willReturn(['user2']);
+ ->willReturn(['user2' => new \OC\User\User('user2', null, $this->dispatcher)]);
$users = $group->searchUsers('2');
$this->assertEquals(1, count($users));
- $user2 = $users['user2'];
+ $user2 = reset($users);
$this->assertEquals('user2', $user2->getUID());
}
@@ -348,14 +348,14 @@ class GroupTest extends \Test\TestCase {
$group = new \OC\Group\Group('group1', [$backend], $this->dispatcher, $userManager);
$backend->expects($this->once())
- ->method('usersInGroup')
+ ->method('searchInGroup')
->with('group1', 'user', 1, 1)
- ->willReturn(['user2']);
+ ->willReturn(['user2' => new \OC\User\User('user2', null, $this->dispatcher)]);
$users = $group->searchUsers('user', 1, 1);
$this->assertEquals(1, count($users));
- $user2 = $users['user2'];
+ $user2 = reset($users);
$this->assertEquals('user2', $user2->getUID());
}
@@ -370,19 +370,19 @@ class GroupTest extends \Test\TestCase {
$group = new \OC\Group\Group('group1', [$backend1, $backend2], $this->dispatcher, $userManager);
$backend1->expects($this->once())
- ->method('usersInGroup')
+ ->method('searchInGroup')
->with('group1', 'user', 2, 1)
- ->willReturn(['user2']);
+ ->willReturn(['user2' => new \OC\User\User('user2', null, $this->dispatcher)]);
$backend2->expects($this->once())
- ->method('usersInGroup')
+ ->method('searchInGroup')
->with('group1', 'user', 2, 1)
- ->willReturn(['user1']);
+ ->willReturn(['user1' => new \OC\User\User('user1', null, $this->dispatcher)]);
$users = $group->searchUsers('user', 2, 1);
$this->assertEquals(2, count($users));
- $user2 = $users['user2'];
- $user1 = $users['user1'];
+ $user2 = reset($users);
+ $user1 = next($users);
$this->assertEquals('user2', $user2->getUID());
$this->assertEquals('user1', $user1->getUID());
}
diff --git a/tests/lib/Group/ManagerTest.php b/tests/lib/Group/ManagerTest.php
index 5e29f974706..710d3888d55 100644
--- a/tests/lib/Group/ManagerTest.php
+++ b/tests/lib/Group/ManagerTest.php
@@ -24,8 +24,10 @@
namespace Test\Group;
use OC\Group\Database;
+use OC\User\User;
use OC\User\Manager;
use OCP\GroupInterface;
+use OCP\Group\Backend\ISearchableGroupBackend;
use OCP\ICacheFactory;
use OCP\IUser;
use PHPUnit\Framework\MockObject\MockObject;
@@ -33,6 +35,9 @@ use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Test\TestCase;
+interface ISearchableGroupInterface extends ISearchableGroupBackend, GroupInterface {
+}
+
class ManagerTest extends TestCase {
/** @var Manager|MockObject */
protected $userManager;
@@ -78,7 +83,7 @@ class ManagerTest extends TestCase {
}
// need to declare it this way due to optional methods
// thanks to the implementsActions logic
- $backend = $this->getMockBuilder(GroupInterface::class)
+ $backend = $this->getMockBuilder(ISearchableGroupInterface::class)
->disableOriginalConstructor()
->setMethods([
'getGroupDetails',
@@ -91,6 +96,7 @@ class ManagerTest extends TestCase {
'createGroup',
'addToGroup',
'removeFromGroup',
+ 'searchInGroup',
])
->getMock();
$backend->expects($this->any())
@@ -724,7 +730,7 @@ class ManagerTest extends TestCase {
public function testDisplayNamesInGroupWithOneUserBackendAndSearchEmpty() {
/**
- * @var \PHPUnit\Framework\MockObject\MockObject | \OC\Group\Backend $backend
+ * @var \PHPUnit\Framework\MockObject\MockObject|\OC\Group\Backend $backend
*/
$backend = $this->getTestBackend();
$backend->expects($this->exactly(1))
@@ -733,22 +739,11 @@ class ManagerTest extends TestCase {
->willReturn(true);
$backend->expects($this->once())
- ->method('usersInGroup')
+ ->method('searchInGroup')
->with('testgroup', '', -1, 0)
- ->willReturn(['user2', 'user33']);
+ ->willReturn(['user2' => $this->getTestUser('user2'), 'user33' => $this->getTestUser('user33')]);
- $this->userManager->expects($this->any())
- ->method('get')
- ->willReturnCallback(function ($uid) {
- switch ($uid) {
- case 'user1': return $this->getTestUser('user1');
- case 'user2': return $this->getTestUser('user2');
- case 'user3': return $this->getTestUser('user3');
- case 'user33': return $this->getTestUser('user33');
- default:
- return null;
- }
- });
+ $this->userManager->expects($this->never())->method('get');
$manager = new \OC\Group\Manager($this->userManager, $this->dispatcher, $this->logger, $this->cache);
$manager->addBackend($backend);
@@ -772,22 +767,11 @@ class ManagerTest extends TestCase {
->willReturn(true);
$backend->expects($this->once())
- ->method('usersInGroup')
+ ->method('searchInGroup')
->with('testgroup', '', 1, 0)
- ->willReturn(['user2']);
+ ->willReturn([new User('user2', null, $this->dispatcher)]);
- $this->userManager->expects($this->any())
- ->method('get')
- ->willReturnCallback(function ($uid) {
- switch ($uid) {
- case 'user1': return $this->getTestUser('user1');
- case 'user2': return $this->getTestUser('user2');
- case 'user3': return $this->getTestUser('user3');
- case 'user33': return $this->getTestUser('user33');
- default:
- return null;
- }
- });
+ $this->userManager->expects($this->never())->method('get');
$manager = new \OC\Group\Manager($this->userManager, $this->dispatcher, $this->logger, $this->cache);
$manager->addBackend($backend);
@@ -811,22 +795,11 @@ class ManagerTest extends TestCase {
->willReturn(true);
$backend->expects($this->once())
- ->method('usersInGroup')
+ ->method('searchInGroup')
->with('testgroup', '', 1, 1)
- ->willReturn(['user33']);
+ ->willReturn(['user33' => $this->getTestUser('user33')]);
- $this->userManager->expects($this->any())
- ->method('get')
- ->willReturnCallback(function ($uid) {
- switch ($uid) {
- case 'user1': return $this->getTestUser('user1');
- case 'user2': return $this->getTestUser('user2');
- case 'user3': return $this->getTestUser('user3');
- case 'user33': return $this->getTestUser('user33');
- default:
- return null;
- }
- });
+ $this->userManager->expects($this->never())->method('get');
$manager = new \OC\Group\Manager($this->userManager, $this->dispatcher, $this->logger, $this->cache);
$manager->addBackend($backend);
diff --git a/tests/lib/Template/JSResourceLocatorTest.php b/tests/lib/Template/JSResourceLocatorTest.php
index 627fe676680..9ac6a32e22c 100644
--- a/tests/lib/Template/JSResourceLocatorTest.php
+++ b/tests/lib/Template/JSResourceLocatorTest.php
@@ -135,9 +135,8 @@ class JSResourceLocatorTest extends \Test\TestCase {
$this->assertEquals($expectedWebRoot, $webRoot);
$this->assertEquals($expectedFile, $file);
- array_pop(\OC::$APPSROOTS);
- //unlink($new_apps_path_symlink);
- //$this->rrmdir($new_apps_path);
+ unlink($new_apps_path_symlink);
+ $this->rrmdir($new_apps_path);
}
public function testFindModuleJSWithFallback() {
@@ -165,7 +164,6 @@ class JSResourceLocatorTest extends \Test\TestCase {
$resources = $locator->getResources();
$this->assertCount(3, $resources);
- $expectedRoot = $new_apps_path . '/test-js-app';
$expectedWebRoot = \OC::$WEBROOT . '/js-apps-test/test-js-app';
$expectedFiles = ['module.mjs', 'both.mjs', 'plain.js'];
@@ -173,8 +171,7 @@ class JSResourceLocatorTest extends \Test\TestCase {
$this->assertEquals($expectedWebRoot, $resources[$idx][1]);
$this->assertEquals($expectedFiles[$idx], $resources[$idx][2]);
}
-
- array_pop(\OC::$APPSROOTS);
+
$this->rrmdir($new_apps_path);
}
}
diff --git a/tests/lib/Util/Group/Dummy.php b/tests/lib/Util/Group/Dummy.php
index 3735a5e1167..a864c8ce9d9 100644
--- a/tests/lib/Util/Group/Dummy.php
+++ b/tests/lib/Util/Group/Dummy.php
@@ -29,12 +29,18 @@
namespace Test\Util\Group;
-use OC\Group\Backend;
+use Test\Util\User\Dummy as DummyUser;
+use OCP\Group\Backend\ABackend;
+use OCP\Group\Backend\IDeleteGroupBackend;
+use OCP\Group\Backend\IAddToGroupBackend;
+use OCP\Group\Backend\IRemoveFromGroupBackend;
+use OCP\Group\Backend\ICreateGroupBackend;
+use OCP\Group\Backend\ICountUsersBackend;
/**
- * dummy group backend, does not keep state, only for testing use
+ * Dummy group backend, does not keep state, only for testing use
*/
-class Dummy extends Backend {
+class Dummy extends ABackend implements ICreateGroupBackend, IDeleteGroupBackend, IAddToGroupBackend, IRemoveFromGroupBackend, ICountUsersBackend {
private $groups = [];
/**
* Try to create a new group
@@ -44,7 +50,7 @@ class Dummy extends Backend {
* Tries to create a new group. If the group name already exists, false will
* be returned.
*/
- public function createGroup($gid) {
+ public function createGroup(string $gid): bool {
if (!isset($this->groups[$gid])) {
$this->groups[$gid] = [];
return true;
@@ -60,7 +66,7 @@ class Dummy extends Backend {
*
* Deletes a group and removes it from the group_user-table
*/
- public function deleteGroup($gid) {
+ public function deleteGroup(string $gid): bool {
if (isset($this->groups[$gid])) {
unset($this->groups[$gid]);
return true;
@@ -93,7 +99,7 @@ class Dummy extends Backend {
*
* Adds a user to a group.
*/
- public function addToGroup($uid, $gid) {
+ public function addToGroup(string $uid, string $gid): bool {
if (isset($this->groups[$gid])) {
if (array_search($uid, $this->groups[$gid]) === false) {
$this->groups[$gid][] = $uid;
@@ -114,7 +120,7 @@ class Dummy extends Backend {
*
* removes the user from a group.
*/
- public function removeFromGroup($uid, $gid) {
+ public function removeFromGroup(string $uid, string $gid): bool {
if (isset($this->groups[$gid])) {
if (($index = array_search($uid, $this->groups[$gid])) !== false) {
unset($this->groups[$gid][$index]);
@@ -192,6 +198,25 @@ class Dummy extends Backend {
}
}
+ public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array {
+ if (isset($this->groups[$gid])) {
+ if (empty($search)) {
+ $length = $limit < 0 ? null : $limit;
+ $users = array_slice($this->groups[$gid], $offset, $length);
+ return array_map(fn ($user) => new DummyUser($user, ''));
+ }
+ $result = [];
+ foreach ($this->groups[$gid] as $user) {
+ if (stripos($user, $search) !== false) {
+ $result[$user] = new DummyUser($user, '');
+ }
+ }
+ return $result;
+ } else {
+ return [];
+ }
+ }
+
/**
* get the number of all users in a group
* @param string $gid
@@ -200,7 +225,7 @@ class Dummy extends Backend {
* @param int $offset
* @return int
*/
- public function countUsersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
+ public function countUsersInGroup(string $gid, string $search = ''): int {
if (isset($this->groups[$gid])) {
if (empty($search)) {
return count($this->groups[$gid]);
@@ -213,5 +238,10 @@ class Dummy extends Backend {
}
return $count;
}
+ return 0;
+ }
+
+ public function groupExists($gid) {
+ return isset($this->groups[$gid]);
}
}