summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/dav/l10n/cs.js3
-rw-r--r--apps/dav/l10n/cs.json3
-rw-r--r--apps/dav/l10n/de_DE.js3
-rw-r--r--apps/dav/l10n/de_DE.json3
-rw-r--r--apps/dav/l10n/pl.js3
-rw-r--r--apps/dav/l10n/pl.json3
-rw-r--r--apps/dav/l10n/zh_CN.js3
-rw-r--r--apps/dav/l10n/zh_CN.json3
-rw-r--r--apps/dav/l10n/zh_HK.js3
-rw-r--r--apps/dav/l10n/zh_HK.json3
-rw-r--r--apps/dav/l10n/zh_TW.js3
-rw-r--r--apps/dav/l10n/zh_TW.json3
-rw-r--r--apps/dav/lib/CalDAV/WebcalCaching/Plugin.php5
-rw-r--r--apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php4
-rw-r--r--apps/encryption/lib/Crypto/Crypt.php27
-rw-r--r--apps/files/l10n/hu.js4
-rw-r--r--apps/files/l10n/hu.json4
-rw-r--r--apps/files/l10n/zh_HK.js2
-rw-r--r--apps/files/l10n/zh_HK.json2
-rw-r--r--apps/provisioning_api/appinfo/routes.php1
-rw-r--r--apps/provisioning_api/lib/Controller/AUserData.php14
-rw-r--r--apps/provisioning_api/lib/Controller/UsersController.php135
-rw-r--r--apps/provisioning_api/tests/Controller/UsersControllerTest.php20
-rw-r--r--apps/settings/l10n/fa.js2
-rw-r--r--apps/settings/l10n/fa.json2
-rw-r--r--apps/settings/l10n/zh_HK.js2
-rw-r--r--apps/settings/l10n/zh_HK.json2
-rw-r--r--apps/user_status/l10n/sc.js38
-rw-r--r--apps/user_status/l10n/sc.json36
29 files changed, 297 insertions, 39 deletions
diff --git a/apps/dav/l10n/cs.js b/apps/dav/l10n/cs.js
index 3fc261855a0..2c22a20c2db 100644
--- a/apps/dav/l10n/cs.js
+++ b/apps/dav/l10n/cs.js
@@ -77,8 +77,11 @@ OC.L10N.register(
"Description: %s" : "Popis: %s",
"Where: %s" : "Kde: %s",
"%1$s via %2$s" : "%1$s prostřednictvím %2$s",
+ "Cancelled: %1$s" : "Zrušeno: %1$s",
"Invitation canceled" : "Pozvánka zrušena",
+ "Re: %1$s" : "Odp.: %1$s",
"Invitation updated" : "Pozvánka aktualizována",
+ "Invitation: %1$s" : "Pozvánka: %1$s",
"Invitation" : "Pozvání",
"Title:" : "Název:",
"Time:" : "Čas:",
diff --git a/apps/dav/l10n/cs.json b/apps/dav/l10n/cs.json
index f5ac115990d..af58f56c931 100644
--- a/apps/dav/l10n/cs.json
+++ b/apps/dav/l10n/cs.json
@@ -75,8 +75,11 @@
"Description: %s" : "Popis: %s",
"Where: %s" : "Kde: %s",
"%1$s via %2$s" : "%1$s prostřednictvím %2$s",
+ "Cancelled: %1$s" : "Zrušeno: %1$s",
"Invitation canceled" : "Pozvánka zrušena",
+ "Re: %1$s" : "Odp.: %1$s",
"Invitation updated" : "Pozvánka aktualizována",
+ "Invitation: %1$s" : "Pozvánka: %1$s",
"Invitation" : "Pozvání",
"Title:" : "Název:",
"Time:" : "Čas:",
diff --git a/apps/dav/l10n/de_DE.js b/apps/dav/l10n/de_DE.js
index e24b3aaf3b2..7f24cc87297 100644
--- a/apps/dav/l10n/de_DE.js
+++ b/apps/dav/l10n/de_DE.js
@@ -77,8 +77,11 @@ OC.L10N.register(
"Description: %s" : "Beschreibung: %s",
"Where: %s" : "Ort: %s",
"%1$s via %2$s" : "%1$s über %2$s",
+ "Cancelled: %1$s" : "Abgesagt: %1$s",
"Invitation canceled" : "Einladung abgebrochen",
+ "Re: %1$s" : "Re: %1$s",
"Invitation updated" : "Einladung aktualisiert",
+ "Invitation: %1$s" : "Einladung: %1$s",
"Invitation" : "Einladung",
"Title:" : "Titel:",
"Time:" : "Zeit:",
diff --git a/apps/dav/l10n/de_DE.json b/apps/dav/l10n/de_DE.json
index 729938d6437..2483c64f5e3 100644
--- a/apps/dav/l10n/de_DE.json
+++ b/apps/dav/l10n/de_DE.json
@@ -75,8 +75,11 @@
"Description: %s" : "Beschreibung: %s",
"Where: %s" : "Ort: %s",
"%1$s via %2$s" : "%1$s über %2$s",
+ "Cancelled: %1$s" : "Abgesagt: %1$s",
"Invitation canceled" : "Einladung abgebrochen",
+ "Re: %1$s" : "Re: %1$s",
"Invitation updated" : "Einladung aktualisiert",
+ "Invitation: %1$s" : "Einladung: %1$s",
"Invitation" : "Einladung",
"Title:" : "Titel:",
"Time:" : "Zeit:",
diff --git a/apps/dav/l10n/pl.js b/apps/dav/l10n/pl.js
index d7fadb386d8..f2926b29767 100644
--- a/apps/dav/l10n/pl.js
+++ b/apps/dav/l10n/pl.js
@@ -77,8 +77,11 @@ OC.L10N.register(
"Description: %s" : "Opis: %s",
"Where: %s" : "Gdzie: %s",
"%1$s via %2$s" : "%1$s przez %2$s",
+ "Cancelled: %1$s" : "Anulowane: %1$s",
"Invitation canceled" : "Zaproszenie anulowane",
+ "Re: %1$s" : "Odp: %1$s",
"Invitation updated" : "Zaproszenie zaktualizowane",
+ "Invitation: %1$s" : "Zaproszenie: %1$s",
"Invitation" : "Zaproszenie",
"Title:" : "Tytuł:",
"Time:" : "Czas:",
diff --git a/apps/dav/l10n/pl.json b/apps/dav/l10n/pl.json
index 448bc2d212e..ef9ea9e8abe 100644
--- a/apps/dav/l10n/pl.json
+++ b/apps/dav/l10n/pl.json
@@ -75,8 +75,11 @@
"Description: %s" : "Opis: %s",
"Where: %s" : "Gdzie: %s",
"%1$s via %2$s" : "%1$s przez %2$s",
+ "Cancelled: %1$s" : "Anulowane: %1$s",
"Invitation canceled" : "Zaproszenie anulowane",
+ "Re: %1$s" : "Odp: %1$s",
"Invitation updated" : "Zaproszenie zaktualizowane",
+ "Invitation: %1$s" : "Zaproszenie: %1$s",
"Invitation" : "Zaproszenie",
"Title:" : "Tytuł:",
"Time:" : "Czas:",
diff --git a/apps/dav/l10n/zh_CN.js b/apps/dav/l10n/zh_CN.js
index 39b1c800b49..c6d394f2f0f 100644
--- a/apps/dav/l10n/zh_CN.js
+++ b/apps/dav/l10n/zh_CN.js
@@ -77,8 +77,11 @@ OC.L10N.register(
"Description: %s" : "描述:%s",
"Where: %s" : "地点:%s",
"%1$s via %2$s" : "%1$s 通过 %2$s",
+ "Cancelled: %1$s" : "已取消:%1$s",
"Invitation canceled" : "邀请已取消",
+ "Re: %1$s" : "回复:%1$s",
"Invitation updated" : "邀请已更新",
+ "Invitation: %1$s" : "邀请:%1$s",
"Invitation" : "邀请",
"Title:" : "标题:",
"Time:" : "时间:",
diff --git a/apps/dav/l10n/zh_CN.json b/apps/dav/l10n/zh_CN.json
index 91d04bd55b4..14881f507a8 100644
--- a/apps/dav/l10n/zh_CN.json
+++ b/apps/dav/l10n/zh_CN.json
@@ -75,8 +75,11 @@
"Description: %s" : "描述:%s",
"Where: %s" : "地点:%s",
"%1$s via %2$s" : "%1$s 通过 %2$s",
+ "Cancelled: %1$s" : "已取消:%1$s",
"Invitation canceled" : "邀请已取消",
+ "Re: %1$s" : "回复:%1$s",
"Invitation updated" : "邀请已更新",
+ "Invitation: %1$s" : "邀请:%1$s",
"Invitation" : "邀请",
"Title:" : "标题:",
"Time:" : "时间:",
diff --git a/apps/dav/l10n/zh_HK.js b/apps/dav/l10n/zh_HK.js
index a57554fb497..1df431a21e7 100644
--- a/apps/dav/l10n/zh_HK.js
+++ b/apps/dav/l10n/zh_HK.js
@@ -77,8 +77,11 @@ OC.L10N.register(
"Description: %s" : "描述:%s",
"Where: %s" : "地點:%s",
"%1$s via %2$s" : "%1$s 由 %2$s",
+ "Cancelled: %1$s" : "已取消:%1$s",
"Invitation canceled" : "邀請被取消了",
+ "Re: %1$s" : "關於: %1$s",
"Invitation updated" : "邀請已更新",
+ "Invitation: %1$s" : "邀請:%1$s",
"Invitation" : "邀請",
"Title:" : "標題:",
"Time:" : "時間:",
diff --git a/apps/dav/l10n/zh_HK.json b/apps/dav/l10n/zh_HK.json
index a1c3ef6a91c..72baf354de5 100644
--- a/apps/dav/l10n/zh_HK.json
+++ b/apps/dav/l10n/zh_HK.json
@@ -75,8 +75,11 @@
"Description: %s" : "描述:%s",
"Where: %s" : "地點:%s",
"%1$s via %2$s" : "%1$s 由 %2$s",
+ "Cancelled: %1$s" : "已取消:%1$s",
"Invitation canceled" : "邀請被取消了",
+ "Re: %1$s" : "關於: %1$s",
"Invitation updated" : "邀請已更新",
+ "Invitation: %1$s" : "邀請:%1$s",
"Invitation" : "邀請",
"Title:" : "標題:",
"Time:" : "時間:",
diff --git a/apps/dav/l10n/zh_TW.js b/apps/dav/l10n/zh_TW.js
index c6610f0352d..c7f9e7c0582 100644
--- a/apps/dav/l10n/zh_TW.js
+++ b/apps/dav/l10n/zh_TW.js
@@ -77,8 +77,11 @@ OC.L10N.register(
"Description: %s" : "描述:%s",
"Where: %s" : "地點:%s",
"%1$s via %2$s" : "%1$s 由 %2$s",
+ "Cancelled: %1$s" : "已取消:%1$s",
"Invitation canceled" : "邀請已取消",
+ "Re: %1$s" : "回覆:%1$s",
"Invitation updated" : "邀請已更新",
+ "Invitation: %1$s" : "邀請:%1$s",
"Invitation" : "邀請",
"Title:" : "標題:",
"Time:" : "時間:",
diff --git a/apps/dav/l10n/zh_TW.json b/apps/dav/l10n/zh_TW.json
index ae976ea60eb..9f4a265a5c1 100644
--- a/apps/dav/l10n/zh_TW.json
+++ b/apps/dav/l10n/zh_TW.json
@@ -75,8 +75,11 @@
"Description: %s" : "描述:%s",
"Where: %s" : "地點:%s",
"%1$s via %2$s" : "%1$s 由 %2$s",
+ "Cancelled: %1$s" : "已取消:%1$s",
"Invitation canceled" : "邀請已取消",
+ "Re: %1$s" : "回覆:%1$s",
"Invitation updated" : "邀請已更新",
+ "Invitation: %1$s" : "邀請:%1$s",
"Invitation" : "邀請",
"Title:" : "標題:",
"Time:" : "時間:",
diff --git a/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php b/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php
index 13aef7ed227..3dd8a7c81e5 100644
--- a/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php
+++ b/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php
@@ -40,9 +40,12 @@ class Plugin extends ServerPlugin {
* list of regular expressions for calendar user agents,
* that do not support subscriptions on their own
*
+ * /^MSFT-WIN-3/ - Windows 10 Calendar
* @var string[]
*/
- public const ENABLE_FOR_CLIENTS = [];
+ public const ENABLE_FOR_CLIENTS = [
+ "/^MSFT-WIN-3/"
+ ];
/**
* @var bool
diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
index b848a5d591a..310d266cd57 100644
--- a/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
@@ -31,7 +31,7 @@ class PluginTest extends \Test\TestCase {
$request = $this->createMock(IRequest::class);
$request->expects($this->at(0))
->method('isUserAgent')
- ->with([])
+ ->with(Plugin::ENABLE_FOR_CLIENTS)
->willReturn(false);
$request->expects($this->at(1))
@@ -48,7 +48,7 @@ class PluginTest extends \Test\TestCase {
$request = $this->createMock(IRequest::class);
$request->expects($this->at(0))
->method('isUserAgent')
- ->with([])
+ ->with(Plugin::ENABLE_FOR_CLIENTS)
->willReturn(false);
$request->expects($this->at(1))
diff --git a/apps/encryption/lib/Crypto/Crypt.php b/apps/encryption/lib/Crypto/Crypt.php
index a7d7c024cbb..8a6be4d3809 100644
--- a/apps/encryption/lib/Crypto/Crypt.php
+++ b/apps/encryption/lib/Crypto/Crypt.php
@@ -89,6 +89,9 @@ class Crypt {
/** @var IL10N */
private $l;
+ /** @var string|null */
+ private $currentCipher;
+
/** @var bool */
private $supportLegacy;
@@ -248,12 +251,17 @@ class Crypt {
}
/**
- * return Cipher either from config.php or the default cipher defined in
+ * return cipher either from config.php or the default cipher defined in
* this class
*
* @return string
*/
- public function getCipher() {
+ private function getCachedCipher() {
+ if (isset($this->currentCipher)) {
+ return $this->currentCipher;
+ }
+
+ // Get cipher either from config.php or the default cipher defined in this class
$cipher = $this->config->getSystemValue('cipher', self::DEFAULT_CIPHER);
if (!isset(self::SUPPORTED_CIPHERS_AND_KEY_SIZE[$cipher])) {
$this->logger->warning(
@@ -267,7 +275,18 @@ class Crypt {
$cipher = self::DEFAULT_CIPHER;
}
- return $cipher;
+ // Remember current cipher to avoid frequent lookups
+ $this->currentCipher = $cipher;
+ return $this->currentCipher;
+ }
+
+ /**
+ * return current encryption cipher
+ *
+ * @return string
+ */
+ public function getCipher() {
+ return $this->getCachedCipher();
}
/**
@@ -577,7 +596,7 @@ class Crypt {
throw new GenericEncryptionException('Missing Signature', $this->l->t('Missing Signature'));
}
- // enforce signature for the new 'CTR' ciphers
+ // Enforce signature for the new 'CTR' ciphers
if (!$skipSignatureCheck && $signaturePosition === false && stripos($cipher, 'ctr') !== false) {
throw new GenericEncryptionException('Missing Signature', $this->l->t('Missing Signature'));
}
diff --git a/apps/files/l10n/hu.js b/apps/files/l10n/hu.js
index 6b28fffaa62..9928cf46985 100644
--- a/apps/files/l10n/hu.js
+++ b/apps/files/l10n/hu.js
@@ -79,6 +79,10 @@ OC.L10N.register(
"File name cannot be empty." : "A fájlnév nem lehet semmi.",
"\"/\" is not allowed inside a file name." : "„/” nem szerepelhet fájlnévben.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" nem engedélyetett fájltípus",
+ "Storage of {owner} is full, files cannot be updated or synced anymore!" : "A {owner} felhasználó tárolója megtelt, a fájlok nem frissíthetők és szinkronizálhatók többé!",
+ "Group folder \"{mountPoint}\" is full, files cannot be updated or synced anymore!" : "A csoport mappa \"{mountPoint}\" megtelt, a fájlok nem frissíthetőek vagy szinkronizálhatóak többé!",
+ "External storage \"{mountPoint}\" is full, files cannot be updated or synced anymore!" : "A külső tároló \"{mountPoint}\" megtelt, a fájlok nem frissíthetőek vagy szinkronizálhatóak többé!",
+ "Your storage is full, files cannot be updated or synced anymore!" : "A tároló megtelt, a fájlok nem frissíthetőek vagy szinkronizálhatóak többé!",
"Storage of {owner} is almost full ({usedSpacePercent}%)." : "A(z) {owner} tárhelye majdnem megtelt ({usedSpacePercent}%).",
"Group folder \"{mountPoint}\" is almost full ({usedSpacePercent}%)." : "A(z) \"{mountPoint}\" csoportmappa majdnem megtelt ({usedSpacePercent}%).",
"External storage \"{mountPoint}\" is almost full ({usedSpacePercent}%)." : "A(z) „{mountPoint}” külső tárhely majdnem megtelt ({usedSpacePercent}%).",
diff --git a/apps/files/l10n/hu.json b/apps/files/l10n/hu.json
index 4c11e607329..d0015fb6635 100644
--- a/apps/files/l10n/hu.json
+++ b/apps/files/l10n/hu.json
@@ -77,6 +77,10 @@
"File name cannot be empty." : "A fájlnév nem lehet semmi.",
"\"/\" is not allowed inside a file name." : "„/” nem szerepelhet fájlnévben.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" nem engedélyetett fájltípus",
+ "Storage of {owner} is full, files cannot be updated or synced anymore!" : "A {owner} felhasználó tárolója megtelt, a fájlok nem frissíthetők és szinkronizálhatók többé!",
+ "Group folder \"{mountPoint}\" is full, files cannot be updated or synced anymore!" : "A csoport mappa \"{mountPoint}\" megtelt, a fájlok nem frissíthetőek vagy szinkronizálhatóak többé!",
+ "External storage \"{mountPoint}\" is full, files cannot be updated or synced anymore!" : "A külső tároló \"{mountPoint}\" megtelt, a fájlok nem frissíthetőek vagy szinkronizálhatóak többé!",
+ "Your storage is full, files cannot be updated or synced anymore!" : "A tároló megtelt, a fájlok nem frissíthetőek vagy szinkronizálhatóak többé!",
"Storage of {owner} is almost full ({usedSpacePercent}%)." : "A(z) {owner} tárhelye majdnem megtelt ({usedSpacePercent}%).",
"Group folder \"{mountPoint}\" is almost full ({usedSpacePercent}%)." : "A(z) \"{mountPoint}\" csoportmappa majdnem megtelt ({usedSpacePercent}%).",
"External storage \"{mountPoint}\" is almost full ({usedSpacePercent}%)." : "A(z) „{mountPoint}” külső tárhely majdnem megtelt ({usedSpacePercent}%).",
diff --git a/apps/files/l10n/zh_HK.js b/apps/files/l10n/zh_HK.js
index 5e66c83a17e..66990490620 100644
--- a/apps/files/l10n/zh_HK.js
+++ b/apps/files/l10n/zh_HK.js
@@ -40,7 +40,7 @@ OC.L10N.register(
"Files" : "檔案",
"Details" : "詳細資料",
"Select" : "選擇",
- "Pending" : "等候中",
+ "Pending" : "待定的",
"Unable to determine date" : "無法確定日期",
"This operation is forbidden" : "此操作被禁止",
"This directory is unavailable, please check the logs or contact the administrator" : "這個目錄無法存取,請檢查伺服器記錄檔或聯絡管理員",
diff --git a/apps/files/l10n/zh_HK.json b/apps/files/l10n/zh_HK.json
index 9a0e2bf63fb..28a340752c9 100644
--- a/apps/files/l10n/zh_HK.json
+++ b/apps/files/l10n/zh_HK.json
@@ -38,7 +38,7 @@
"Files" : "檔案",
"Details" : "詳細資料",
"Select" : "選擇",
- "Pending" : "等候中",
+ "Pending" : "待定的",
"Unable to determine date" : "無法確定日期",
"This operation is forbidden" : "此操作被禁止",
"This directory is unavailable, please check the logs or contact the administrator" : "這個目錄無法存取,請檢查伺服器記錄檔或聯絡管理員",
diff --git a/apps/provisioning_api/appinfo/routes.php b/apps/provisioning_api/appinfo/routes.php
index 8cf57487d3a..2f981e0c924 100644
--- a/apps/provisioning_api/appinfo/routes.php
+++ b/apps/provisioning_api/appinfo/routes.php
@@ -54,6 +54,7 @@ return [
['root' => '/cloud', 'name' => 'Users#getEditableFields', 'url' => '/user/fields', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Users#getEditableFieldsForUser', 'url' => '/user/fields/{userId}', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Users#editUser', 'url' => '/users/{userId}', 'verb' => 'PUT'],
+ ['root' => '/cloud', 'name' => 'Users#editUserMultiValue', 'url' => '/users/{userId}/{collectionName}', 'verb' => 'PUT', 'requirements' => ['collectionName' => '^(?!enable$|disable$)[a-zA-Z0-9_]*$']],
['root' => '/cloud', 'name' => 'Users#wipeUserDevices', 'url' => '/users/{userId}/wipe', 'verb' => 'POST'],
['root' => '/cloud', 'name' => 'Users#deleteUser', 'url' => '/users/{userId}', 'verb' => 'DELETE'],
['root' => '/cloud', 'name' => 'Users#enableUser', 'url' => '/users/{userId}/enable', 'verb' => 'PUT'],
diff --git a/apps/provisioning_api/lib/Controller/AUserData.php b/apps/provisioning_api/lib/Controller/AUserData.php
index c4fa537c2df..e358d282061 100644
--- a/apps/provisioning_api/lib/Controller/AUserData.php
+++ b/apps/provisioning_api/lib/Controller/AUserData.php
@@ -150,6 +150,20 @@ abstract class AUserData extends OCSController {
if ($includeScopes) {
$data[IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX] = $userAccount->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope();
}
+
+ $additionalEmails = $additionalEmailScopes = [];
+ $emailCollection = $userAccount->getPropertyCollection(IAccountManager::COLLECTION_EMAIL);
+ foreach ($emailCollection->getProperties() as $property) {
+ $additionalEmails[] = $property->getValue();
+ if ($includeScopes) {
+ $additionalEmailScopes[] = $property->getScope();
+ }
+ }
+ $data[IAccountManager::COLLECTION_EMAIL] = $additionalEmails;
+ if ($includeScopes) {
+ $data[IAccountManager::COLLECTION_EMAIL . self::SCOPE_SUFFIX] = $additionalEmailScopes;
+ }
+
$data[IAccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
if ($includeScopes) {
$data[IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX] = $userAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getScope();
diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php
index 256077e9ae9..d94e8fed8a8 100644
--- a/apps/provisioning_api/lib/Controller/UsersController.php
+++ b/apps/provisioning_api/lib/Controller/UsersController.php
@@ -52,7 +52,8 @@ use OC\KnownUser\KnownUserService;
use OC\User\Backend;
use OCA\Settings\Mailer\NewUserMailHelper;
use OCP\Accounts\IAccountManager;
-use OCP\App\IAppManager;
+use OCP\Accounts\IAccountProperty;
+use OCP\Accounts\PropertyDoesNotExistException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSException;
@@ -75,8 +76,6 @@ use Psr\Log\LoggerInterface;
class UsersController extends AUserData {
- /** @var IAppManager */
- private $appManager;
/** @var IURLGenerator */
protected $urlGenerator;
/** @var LoggerInterface */
@@ -98,7 +97,6 @@ class UsersController extends AUserData {
IRequest $request,
IUserManager $userManager,
IConfig $config,
- IAppManager $appManager,
IGroupManager $groupManager,
IUserSession $userSession,
IAccountManager $accountManager,
@@ -119,7 +117,6 @@ class UsersController extends AUserData {
$accountManager,
$l10nFactory);
- $this->appManager = $appManager;
$this->urlGenerator = $urlGenerator;
$this->logger = $logger;
$this->l10nFactory = $l10nFactory;
@@ -592,6 +589,7 @@ class UsersController extends AUserData {
$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
}
+ $permittedFields[] = IAccountManager::COLLECTION_EMAIL;
$permittedFields[] = IAccountManager::PROPERTY_PHONE;
$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
@@ -605,6 +603,92 @@ class UsersController extends AUserData {
* @NoSubAdminRequired
* @PasswordConfirmationRequired
*
+ * @throws OCSException
+ */
+ public function editUserMultiValue(
+ string $userId,
+ string $collectionName,
+ string $key,
+ string $value
+ ): DataResponse {
+ $currentLoggedInUser = $this->userSession->getUser();
+ if ($currentLoggedInUser === null) {
+ throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
+ }
+
+ $targetUser = $this->userManager->get($userId);
+ if ($targetUser === null) {
+ throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
+ }
+
+ $permittedFields = [];
+ if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
+ // Editing self (display, email)
+ $permittedFields[] = IAccountManager::COLLECTION_EMAIL;
+ $permittedFields[] = IAccountManager::COLLECTION_EMAIL . self::SCOPE_SUFFIX;
+ } else {
+ // Check if admin / subadmin
+ $subAdminManager = $this->groupManager->getSubAdmin();
+ if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())
+ || $subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
+ // They have permissions over the user
+
+ $permittedFields[] = IAccountManager::COLLECTION_EMAIL;
+ } else {
+ // No rights
+ throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
+ }
+ }
+
+ // Check if permitted to edit this field
+ if (!in_array($collectionName, $permittedFields)) {
+ throw new OCSException('', 103);
+ }
+
+ switch ($collectionName) {
+ case IAccountManager::COLLECTION_EMAIL:
+ $userAccount = $this->accountManager->getAccount($targetUser);
+ $mailCollection = $userAccount->getPropertyCollection(IAccountManager::COLLECTION_EMAIL);
+ $mailCollection->removePropertyByValue($key);
+ if ($value !== '') {
+ $mailCollection->addPropertyWithDefaults($value);
+ }
+ $this->accountManager->updateAccount($userAccount);
+ break;
+
+ case IAccountManager::COLLECTION_EMAIL . self::SCOPE_SUFFIX:
+ $userAccount = $this->accountManager->getAccount($targetUser);
+ $mailCollection = $userAccount->getPropertyCollection(IAccountManager::COLLECTION_EMAIL);
+ $targetProperty = null;
+ foreach ($mailCollection->getProperties() as $property) {
+ if ($property->getValue() === $key) {
+ $targetProperty = $property;
+ break;
+ }
+ }
+ if ($targetProperty instanceof IAccountProperty) {
+ try {
+ $targetProperty->setScope($value);
+ $this->accountManager->updateAccount($userAccount);
+ } catch (\InvalidArgumentException $e) {
+ throw new OCSException('', 102);
+ }
+ } else {
+ throw new OCSException('', 102);
+ }
+ break;
+
+ default:
+ throw new OCSException('', 103);
+ }
+ return new DataResponse();
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoSubAdminRequired
+ * @PasswordConfirmationRequired
+ *
* edit users
*
* @param string $userId
@@ -636,6 +720,8 @@ class UsersController extends AUserData {
$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX;
$permittedFields[] = IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX;
+ $permittedFields[] = IAccountManager::COLLECTION_EMAIL;
+
$permittedFields[] = 'password';
if ($this->config->getSystemValue('force_language', false) === false ||
$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
@@ -674,6 +760,7 @@ class UsersController extends AUserData {
$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
}
$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
+ $permittedFields[] = IAccountManager::COLLECTION_EMAIL;
$permittedFields[] = 'password';
$permittedFields[] = 'language';
$permittedFields[] = 'locale';
@@ -746,24 +833,42 @@ class UsersController extends AUserData {
throw new OCSException('', 102);
}
break;
+ case IAccountManager::COLLECTION_EMAIL:
+ if (filter_var($value, FILTER_VALIDATE_EMAIL) && $value !== $targetUser->getEMailAddress()) {
+ $userAccount = $this->accountManager->getAccount($targetUser);
+ $mailCollection = $userAccount->getPropertyCollection(IAccountManager::COLLECTION_EMAIL);
+ foreach ($mailCollection->getProperties() as $property) {
+ if ($property->getValue() === $value) {
+ break;
+ }
+ }
+ $mailCollection->addPropertyWithDefaults($value);
+ $this->accountManager->updateAccount($userAccount);
+ } else {
+ throw new OCSException('', 102);
+ }
+ break;
case IAccountManager::PROPERTY_PHONE:
case IAccountManager::PROPERTY_ADDRESS:
case IAccountManager::PROPERTY_WEBSITE:
case IAccountManager::PROPERTY_TWITTER:
$userAccount = $this->accountManager->getAccount($targetUser);
- $userProperty = $userAccount->getProperty($key);
- if ($userProperty->getValue() !== $value) {
- try {
- $userProperty->setValue($value);
- $this->accountManager->updateAccount($userAccount);
-
- if ($userProperty->getName() === IAccountManager::PROPERTY_PHONE) {
- $this->knownUserService->deleteByContactUserId($targetUser->getUID());
+ try {
+ $userProperty = $userAccount->getProperty($key);
+ if ($userProperty->getValue() !== $value) {
+ try {
+ $userProperty->setValue($value);
+ if ($userProperty->getName() === IAccountManager::PROPERTY_PHONE) {
+ $this->knownUserService->deleteByContactUserId($targetUser->getUID());
+ }
+ } catch (\InvalidArgumentException $e) {
+ throw new OCSException('Invalid ' . $e->getMessage(), 102);
}
- } catch (\InvalidArgumentException $e) {
- throw new OCSException('Invalid ' . $e->getMessage(), 102);
}
+ } catch (PropertyDoesNotExistException $e) {
+ $userAccount->setProperty($key, $value, IAccountManager::SCOPE_PRIVATE, IAccountManager::NOT_VERIFIED);
}
+ $this->accountManager->updateAccount($userAccount);
break;
case IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX:
case IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX:
diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php
index 742335a919a..238bac34307 100644
--- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php
+++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php
@@ -50,7 +50,6 @@ use OCA\Settings\Mailer\NewUserMailHelper;
use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
use OCP\Accounts\IAccountProperty;
-use OCP\App\IAppManager;
use OCP\AppFramework\Http\DataResponse;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
@@ -77,8 +76,6 @@ class UsersControllerTest extends TestCase {
protected $userManager;
/** @var IConfig|MockObject */
protected $config;
- /** @var IAppManager|MockObject */
- protected $appManager;
/** @var Manager|MockObject */
protected $groupManager;
/** @var IUserSession|MockObject */
@@ -111,7 +108,6 @@ class UsersControllerTest extends TestCase {
$this->userManager = $this->createMock(IUserManager::class);
$this->config = $this->createMock(IConfig::class);
- $this->appManager = $this->createMock(IAppManager::class);
$this->groupManager = $this->createMock(Manager::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->logger = $this->createMock(LoggerInterface::class);
@@ -131,7 +127,6 @@ class UsersControllerTest extends TestCase {
$this->request,
$this->userManager,
$this->config,
- $this->appManager,
$this->groupManager,
$this->userSession,
$this->accountManager,
@@ -395,7 +390,6 @@ class UsersControllerTest extends TestCase {
$this->request,
$this->userManager,
$this->config,
- $this->appManager,
$this->groupManager,
$this->userSession,
$this->accountManager,
@@ -1071,7 +1065,8 @@ class UsersControllerTest extends TestCase {
'backendCapabilities' => [
'setDisplayName' => true,
'setPassword' => true,
- ]
+ ],
+ 'additional_mail' => [],
];
$this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID']));
}
@@ -1198,7 +1193,8 @@ class UsersControllerTest extends TestCase {
'backendCapabilities' => [
'setDisplayName' => true,
'setPassword' => true,
- ]
+ ],
+ 'additional_mail' => [],
];
$this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID']));
}
@@ -1363,7 +1359,8 @@ class UsersControllerTest extends TestCase {
'backendCapabilities' => [
'setDisplayName' => false,
'setPassword' => false,
- ]
+ ],
+ 'additional_mail' => [],
];
$this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID']));
}
@@ -3437,7 +3434,6 @@ class UsersControllerTest extends TestCase {
$this->request,
$this->userManager,
$this->config,
- $this->appManager,
$this->groupManager,
$this->userSession,
$this->accountManager,
@@ -3510,7 +3506,6 @@ class UsersControllerTest extends TestCase {
$this->request,
$this->userManager,
$this->config,
- $this->appManager,
$this->groupManager,
$this->userSession,
$this->accountManager,
@@ -3848,6 +3843,7 @@ class UsersControllerTest extends TestCase {
public function dataGetEditableFields() {
return [
[false, ISetDisplayNameBackend::class, [
+ IAccountManager::COLLECTION_EMAIL,
IAccountManager::PROPERTY_PHONE,
IAccountManager::PROPERTY_ADDRESS,
IAccountManager::PROPERTY_WEBSITE,
@@ -3856,6 +3852,7 @@ class UsersControllerTest extends TestCase {
[true, ISetDisplayNameBackend::class, [
IAccountManager::PROPERTY_DISPLAYNAME,
IAccountManager::PROPERTY_EMAIL,
+ IAccountManager::COLLECTION_EMAIL,
IAccountManager::PROPERTY_PHONE,
IAccountManager::PROPERTY_ADDRESS,
IAccountManager::PROPERTY_WEBSITE,
@@ -3863,6 +3860,7 @@ class UsersControllerTest extends TestCase {
]],
[true, UserInterface::class, [
IAccountManager::PROPERTY_EMAIL,
+ IAccountManager::COLLECTION_EMAIL,
IAccountManager::PROPERTY_PHONE,
IAccountManager::PROPERTY_ADDRESS,
IAccountManager::PROPERTY_WEBSITE,
diff --git a/apps/settings/l10n/fa.js b/apps/settings/l10n/fa.js
index 62a82851ce5..8707cff6562 100644
--- a/apps/settings/l10n/fa.js
+++ b/apps/settings/l10n/fa.js
@@ -203,7 +203,7 @@ OC.L10N.register(
"Account deletion" : "حذف حساب کاربری",
"Delete {userid}'s account" : "حساب {userid} را حذف کنید",
"Welcome mail sent!" : "نامه خوش آمديد ارسال شد",
- "Edit User" : "ویرایش کردن کاربر",
+ "Edit User" : "ویرایش کاربر",
"{size} used" : "{size} مورد استفاده",
"New user" : "کاربر جدید",
"Will be autogenerated" : "به صورت خودکار تولید می شود",
diff --git a/apps/settings/l10n/fa.json b/apps/settings/l10n/fa.json
index cbcc894cbfc..2e7ec8b136b 100644
--- a/apps/settings/l10n/fa.json
+++ b/apps/settings/l10n/fa.json
@@ -201,7 +201,7 @@
"Account deletion" : "حذف حساب کاربری",
"Delete {userid}'s account" : "حساب {userid} را حذف کنید",
"Welcome mail sent!" : "نامه خوش آمديد ارسال شد",
- "Edit User" : "ویرایش کردن کاربر",
+ "Edit User" : "ویرایش کاربر",
"{size} used" : "{size} مورد استفاده",
"New user" : "کاربر جدید",
"Will be autogenerated" : "به صورت خودکار تولید می شود",
diff --git a/apps/settings/l10n/zh_HK.js b/apps/settings/l10n/zh_HK.js
index 837fc0e2e72..25e57c40bc5 100644
--- a/apps/settings/l10n/zh_HK.js
+++ b/apps/settings/l10n/zh_HK.js
@@ -273,7 +273,7 @@ OC.L10N.register(
"App bundles" : "應用程式套裝",
"Featured apps" : "精選應用程式",
"{license}-licensed" : "以 {license} 授權",
- "Details" : "詳細資料",
+ "Details" : "細節",
"Changelog" : "變更紀錄",
"by {author}\n{license}" : "作者為 {author}\n{license}",
"Enter group name" : "輸入群組名稱",
diff --git a/apps/settings/l10n/zh_HK.json b/apps/settings/l10n/zh_HK.json
index 69446c1dcfe..e53bbb25d5b 100644
--- a/apps/settings/l10n/zh_HK.json
+++ b/apps/settings/l10n/zh_HK.json
@@ -271,7 +271,7 @@
"App bundles" : "應用程式套裝",
"Featured apps" : "精選應用程式",
"{license}-licensed" : "以 {license} 授權",
- "Details" : "詳細資料",
+ "Details" : "細節",
"Changelog" : "變更紀錄",
"by {author}\n{license}" : "作者為 {author}\n{license}",
"Enter group name" : "輸入群組名稱",
diff --git a/apps/user_status/l10n/sc.js b/apps/user_status/l10n/sc.js
new file mode 100644
index 00000000000..094ea311bd9
--- /dev/null
+++ b/apps/user_status/l10n/sc.js
@@ -0,0 +1,38 @@
+OC.L10N.register(
+ "user_status",
+ {
+ "Recent statuses" : "Istados reghentes",
+ "In a meeting" : "In riunione",
+ "Commuting" : "Biagende",
+ "Out sick" : "In maladia",
+ "Vacationing" : "In vacàntzia",
+ "Working remotely" : "Traballende in remotu",
+ "User status" : "Istadu de s'utente",
+ "Clear status message after" : "Lìmpia su messàgiu de istadu a pustis",
+ "What's your status?" : "Cale est s'istadu tuo?",
+ "Set status" : "Imposta istadu",
+ "Online status" : "Istadu in lìnia",
+ "Status message" : "Messàgiu de istadu",
+ "Clear status message" : "Lìmpia su messàgiu de istadu",
+ "Set status message" : "Imposta messàgiu de istadu",
+ "There was an error saving the status" : "B'at àpidu un'errore sarvende s'istadu",
+ "There was an error clearing the status" : "B'at àpidu un'errore limpiende s'istadu",
+ "No recent status changes" : "Perunu càmbiu de istadu reghente",
+ "Away" : "Ausente",
+ "Do not disturb" : "No istorbes",
+ "{status}, {timestamp}" : "{status}, {timestamp}",
+ "Don't clear" : "Non nche ddu lìmpies",
+ "Today" : "Oe",
+ "This week" : "Custa chida",
+ "Online" : "In lìnia",
+ "Invisible" : "Invisìbile",
+ "Offline" : "Fora de lìnia",
+ "There was an error saving the new status" : "B'at àpidu un'errore sarvende s'istadu nou",
+ "30 minutes" : "30 minutos",
+ "1 hour" : "1 ora",
+ "4 hours" : "4 oras",
+ "Mute all notifications" : "Istuda totu is notìficas",
+ "Appear offline" : "Mustra•ti foras de lìnia",
+ "Clear status after" : "Lìmpia s'istadu a pustis"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/user_status/l10n/sc.json b/apps/user_status/l10n/sc.json
new file mode 100644
index 00000000000..79d695addfa
--- /dev/null
+++ b/apps/user_status/l10n/sc.json
@@ -0,0 +1,36 @@
+{ "translations": {
+ "Recent statuses" : "Istados reghentes",
+ "In a meeting" : "In riunione",
+ "Commuting" : "Biagende",
+ "Out sick" : "In maladia",
+ "Vacationing" : "In vacàntzia",
+ "Working remotely" : "Traballende in remotu",
+ "User status" : "Istadu de s'utente",
+ "Clear status message after" : "Lìmpia su messàgiu de istadu a pustis",
+ "What's your status?" : "Cale est s'istadu tuo?",
+ "Set status" : "Imposta istadu",
+ "Online status" : "Istadu in lìnia",
+ "Status message" : "Messàgiu de istadu",
+ "Clear status message" : "Lìmpia su messàgiu de istadu",
+ "Set status message" : "Imposta messàgiu de istadu",
+ "There was an error saving the status" : "B'at àpidu un'errore sarvende s'istadu",
+ "There was an error clearing the status" : "B'at àpidu un'errore limpiende s'istadu",
+ "No recent status changes" : "Perunu càmbiu de istadu reghente",
+ "Away" : "Ausente",
+ "Do not disturb" : "No istorbes",
+ "{status}, {timestamp}" : "{status}, {timestamp}",
+ "Don't clear" : "Non nche ddu lìmpies",
+ "Today" : "Oe",
+ "This week" : "Custa chida",
+ "Online" : "In lìnia",
+ "Invisible" : "Invisìbile",
+ "Offline" : "Fora de lìnia",
+ "There was an error saving the new status" : "B'at àpidu un'errore sarvende s'istadu nou",
+ "30 minutes" : "30 minutos",
+ "1 hour" : "1 ora",
+ "4 hours" : "4 oras",
+ "Mute all notifications" : "Istuda totu is notìficas",
+ "Appear offline" : "Mustra•ti foras de lìnia",
+ "Clear status after" : "Lìmpia s'istadu a pustis"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file