From 54973c3cf9471dbf6754f7bce23bb620393001e7 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 23 Jan 2023 17:14:38 +0100 Subject: [PATCH 01/59] run kerberos sso test when the action is changed Signed-off-by: Robin Appelman --- .github/workflows/smb-kerberos.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/smb-kerberos.yml b/.github/workflows/smb-kerberos.yml index f47a06fbed794..22b8241d71069 100644 --- a/.github/workflows/smb-kerberos.yml +++ b/.github/workflows/smb-kerberos.yml @@ -6,9 +6,11 @@ on: - stable* paths: - 'apps/files_external/**' + - '.github/workflows/smb-kerberos.yml' pull_request: paths: - 'apps/files_external/**' + - '.github/workflows/smb-kerberos.yml' jobs: smb-kerberos-tests: From 3b577aa5b2bdacca287ad0de0ab0e628d3154105 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 23 Jan 2023 17:30:17 +0100 Subject: [PATCH 02/59] Update kerberos sso test setup to use new user_saml config system Signed-off-by: Robin Appelman --- .github/workflows/smb-kerberos.yml | 24 ++++++++--------- apps/files_external/tests/client-cmd.sh | 6 +++++ apps/files_external/tests/setup-krb.sh | 33 ----------------------- apps/files_external/tests/start-apache.sh | 11 ++++++++ apps/files_external/tests/start-dc.sh | 29 ++++++++++++++++++++ 5 files changed, 58 insertions(+), 45 deletions(-) create mode 100755 apps/files_external/tests/client-cmd.sh delete mode 100755 apps/files_external/tests/setup-krb.sh create mode 100755 apps/files_external/tests/start-apache.sh create mode 100755 apps/files_external/tests/start-dc.sh diff --git a/.github/workflows/smb-kerberos.yml b/.github/workflows/smb-kerberos.yml index 22b8241d71069..896d96e592c81 100644 --- a/.github/workflows/smb-kerberos.yml +++ b/.github/workflows/smb-kerberos.yml @@ -16,7 +16,7 @@ jobs: smb-kerberos-tests: runs-on: ubuntu-latest - name: kerberos + name: smb-kerberos-sso steps: - name: Checkout server @@ -30,9 +30,12 @@ jobs: docker pull icewind1991/samba-krb-test-client - name: Setup AD-DC run: | + cp apps/files_external/tests/*.sh . mkdir data sudo chown -R 33 data apps config - apps/files_external/tests/setup-krb.sh + DC_IP=$(./start-dc.sh) + ./start-apache.sh $DC_IP $PWD + echo "DC_IP=$DC_IP" >> $GITHUB_ENV - name: Set up Nextcloud run: | docker exec --user 33 apache ./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password @@ -41,7 +44,8 @@ jobs: # setup user_saml docker exec --user 33 apache ./occ app:enable user_saml --force docker exec --user 33 apache ./occ config:app:set user_saml type --value 'environment-variable' - docker exec --user 33 apache ./occ config:app:set user_saml general-uid_mapping --value REMOTE_USER + docker exec --user 33 apache ./occ saml:config:create + docker exec --user 33 apache ./occ saml:config:set 1 --general-uid_mapping=REMOTE_USER # setup external storage docker exec --user 33 apache ./occ app:enable files_external --force @@ -51,16 +55,12 @@ jobs: docker exec --user 33 apache ./occ files_external:list - name: Test SSO run: | - mkdir cookies - chmod 0777 cookies + mkdir /tmp/shared/cookies + chmod 0777 /tmp/shared/cookies - DC_IP=$(docker inspect dc --format '{{.NetworkSettings.IPAddress}}') echo "SAML login" - docker run --rm --name client -v $PWD/cookies:/cookies -v /tmp/shared:/shared --dns $DC_IP --hostname client.domain.test icewind1991/samba-krb-test-client \ - curl -c /cookies/jar --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/index.php/apps/user_saml/saml/login + ./client-cmd.sh ${{ env.DC_IP }} curl -c /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/index.php/apps/user_saml/saml/login echo "Check we are logged in" - CONTENT=$(docker run --rm --name client -v $PWD/cookies:/cookies -v /tmp/shared:/shared --dns $DC_IP --hostname client.domain.test icewind1991/samba-krb-test-client \ - curl -b /cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/remote.php/webdav/smb/test.txt) - echo $CONTENT - CONTENT=$(echo $CONTENT | tr -d '[:space:]') + CONTENT=$(./client-cmd.sh ${{ env.DC_IP }} curl -b /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/remote.php/webdav/smb/test.txt) + CONTENT=$(echo $CONTENT | head -n 1 | tr -d '[:space:]') [[ $CONTENT == "testfile" ]] diff --git a/apps/files_external/tests/client-cmd.sh b/apps/files_external/tests/client-cmd.sh new file mode 100755 index 0000000000000..c97045bea4cf4 --- /dev/null +++ b/apps/files_external/tests/client-cmd.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +DC_IP=$1 +shift + +docker run --rm --name client -v /tmp/shared:/shared --dns $DC_IP --hostname client.domain.test icewind1991/samba-krb-test-client $@ diff --git a/apps/files_external/tests/setup-krb.sh b/apps/files_external/tests/setup-krb.sh deleted file mode 100755 index 968ba80529e22..0000000000000 --- a/apps/files_external/tests/setup-krb.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -function getContainerHealth { - docker inspect --format "{{.State.Health.Status}}" $1 -} - -function waitContainer { - while STATUS=$(getContainerHealth $1); [ $STATUS != "healthy" ]; do - if [ $STATUS == "unhealthy" ]; then - echo "Failed!" - exit -1 - fi - printf . - lf=$'\n' - sleep 1 - done - printf "$lf" -} - -mkdir /tmp/shared - -# start the dc -docker run -dit --name dc -v /tmp/shared:/shared --hostname krb.domain.test --cap-add SYS_ADMIN icewind1991/samba-krb-test-dc -DC_IP=$(docker inspect dc --format '{{.NetworkSettings.IPAddress}}') - -waitContainer dc - -# start apache -docker run -d --name apache -v $PWD:/var/www/html -v /tmp/shared:/shared --dns $DC_IP --hostname httpd.domain.test icewind1991/samba-krb-test-apache -APACHE_IP=$(docker inspect apache --format '{{.NetworkSettings.IPAddress}}') - -# add the dns record for apache -docker exec dc samba-tool dns add krb.domain.test domain.test httpd A $APACHE_IP -U administrator --password=passwOrd1 diff --git a/apps/files_external/tests/start-apache.sh b/apps/files_external/tests/start-apache.sh new file mode 100755 index 0000000000000..2c3e178e2efeb --- /dev/null +++ b/apps/files_external/tests/start-apache.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +docker rm -f apache 2>/dev/null > /dev/null + +docker run -d --name apache -v $2:/var/www/html -v /tmp/shared:/shared --dns $1 --hostname httpd.domain.test icewind1991/samba-krb-test-apache 1>&2 +APACHE_IP=$(docker inspect apache --format '{{.NetworkSettings.IPAddress}}') + +# add the dns record for apache +docker exec dc samba-tool dns add krb.domain.test domain.test httpd A $APACHE_IP -U administrator --password=passwOrd1 1>&2 + +echo $APACHE_IP diff --git a/apps/files_external/tests/start-dc.sh b/apps/files_external/tests/start-dc.sh new file mode 100755 index 0000000000000..45fbbfbf0b52d --- /dev/null +++ b/apps/files_external/tests/start-dc.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +function getContainerHealth { + docker inspect --format "{{.State.Health.Status}}" $1 +} + +function waitContainer { + while STATUS=$(getContainerHealth $1); [ $STATUS != "healthy" ]; do + if [ $STATUS == "unhealthy" ]; then + echo "Failed!" 1>&2 + exit -1 + fi + printf . 1>&2 + lf=$'\n' + sleep 1 + done + printf "$lf" 1>&2 +} + +docker rm -f dc 2>/dev/null > /dev/null + +mkdir -p /tmp/shared + +# start the dc +docker run -dit --name dc -v /tmp/shared:/shared --hostname krb.domain.test --cap-add SYS_ADMIN icewind1991/samba-krb-test-dc 1>&2 + +waitContainer dc + +docker inspect dc --format '{{.NetworkSettings.IPAddress}}' From bbb490de5ea22c50e08b9fa8c788ae7ba7de8e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Sun, 22 Jan 2023 11:56:31 +0100 Subject: [PATCH 03/59] Fix event listener race condition on login-form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- core/js/login/authpicker.js | 2 ++ core/templates/loginflow/authpicker.php | 2 +- core/templates/loginflowv2/authpicker.php | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/js/login/authpicker.js b/core/js/login/authpicker.js index 8aaaf3d7361c1..1a94b02d72f95 100644 --- a/core/js/login/authpicker.js +++ b/core/js/login/authpicker.js @@ -10,4 +10,6 @@ jQuery(document).ready(function() { e.preventDefault(); document.location.href = e.target.attributes.action.value }) + + $('#login-form input').removeAttr('disabled'); }) diff --git a/core/templates/loginflow/authpicker.php b/core/templates/loginflow/authpicker.php index 68c53818a9236..3f78081921d3e 100644 --- a/core/templates/loginflow/authpicker.php +++ b/core/templates/loginflow/authpicker.php @@ -47,7 +47,7 @@
- +

diff --git a/core/templates/loginflowv2/authpicker.php b/core/templates/loginflowv2/authpicker.php index b7ff617bd309c..0e18cc99ce15f 100644 --- a/core/templates/loginflowv2/authpicker.php +++ b/core/templates/loginflowv2/authpicker.php @@ -47,7 +47,7 @@
- +

From ba8a50c0591c14a63947bda81915988fb03067fe Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Sat, 28 Jan 2023 03:41:24 +0100 Subject: [PATCH 04/59] fix: Throw `NotFoundExceptionInterface` to fulfill PSR container interface if class not found Signed-off-by: Ferdinand Thiessen --- .../Utility/QueryNotFoundException.php | 41 +++++++++++++++++++ .../AppFramework/Utility/SimpleContainer.php | 5 ++- lib/public/AppFramework/QueryException.php | 2 +- lib/public/IContainer.php | 2 + .../Utility/SimpleContainerTest.php | 27 ++++++++++-- 5 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 lib/private/AppFramework/Utility/QueryNotFoundException.php diff --git a/lib/private/AppFramework/Utility/QueryNotFoundException.php b/lib/private/AppFramework/Utility/QueryNotFoundException.php new file mode 100644 index 0000000000000..04faaa51a4ba0 --- /dev/null +++ b/lib/private/AppFramework/Utility/QueryNotFoundException.php @@ -0,0 +1,41 @@ + + * + * @author Ferdinand Thiessen + * + * @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 . + * + */ + +namespace OC\AppFramework\Utility; + +use OCP\AppFramework\QueryException; +use Psr\Container\NotFoundExceptionInterface; + +/** + * Private implementation of the `Psr\Container\NotFoundExceptionInterface` + * + * QueryNotFoundException is a simple wrapper over the `QueryException` + * to fulfill the PSR Container interface. + * + * You should not catch this class directly but the `NotFoundExceptionInterface`. + */ +class QueryNotFoundException extends QueryException implements NotFoundExceptionInterface { +} diff --git a/lib/private/AppFramework/Utility/SimpleContainer.php b/lib/private/AppFramework/Utility/SimpleContainer.php index 06e9d4a3ec771..89e4204c85e4a 100644 --- a/lib/private/AppFramework/Utility/SimpleContainer.php +++ b/lib/private/AppFramework/Utility/SimpleContainer.php @@ -127,7 +127,8 @@ public function resolve($name) { ' Class can not be instantiated'); } } catch (ReflectionException $e) { - throw new QueryException($baseMsg . ' ' . $e->getMessage()); + // Class does not exist + throw new QueryNotFoundException($baseMsg . ' ' . $e->getMessage()); } } @@ -145,7 +146,7 @@ public function query(string $name, bool $autoload = true) { return $object; } - throw new QueryException('Could not resolve ' . $name . '!'); + throw new QueryNotFoundException('Could not resolve ' . $name . '!'); } /** diff --git a/lib/public/AppFramework/QueryException.php b/lib/public/AppFramework/QueryException.php index 3b73c92e7be51..c525ddd80335b 100644 --- a/lib/public/AppFramework/QueryException.php +++ b/lib/public/AppFramework/QueryException.php @@ -32,7 +32,7 @@ /** * Class QueryException * - * The class extends `NotFoundExceptionInterface` since 20.0.0 + * The class extends `ContainerExceptionInterface` since 20.0.0 * * @since 8.1.0 * @deprecated 20.0.0 catch \Psr\Container\ContainerExceptionInterface diff --git a/lib/public/IContainer.php b/lib/public/IContainer.php index 86595e1e8f7af..b27ddabb8e205 100644 --- a/lib/public/IContainer.php +++ b/lib/public/IContainer.php @@ -33,6 +33,7 @@ use OCP\AppFramework\QueryException; use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class IContainer @@ -70,6 +71,7 @@ public function resolve($name); * @return mixed * @psalm-return ($name is class-string ? T : mixed) * @throws ContainerExceptionInterface if the query could not be resolved + * @throws NotFoundExceptionInterface if the name could not be found within the container * @throws QueryException if the query could not be resolved * @since 6.0.0 * @deprecated 20.0.0 use \Psr\Container\ContainerInterface::get diff --git a/tests/lib/AppFramework/Utility/SimpleContainerTest.php b/tests/lib/AppFramework/Utility/SimpleContainerTest.php index 8caaf517f5ce9..61b3299671b9b 100644 --- a/tests/lib/AppFramework/Utility/SimpleContainerTest.php +++ b/tests/lib/AppFramework/Utility/SimpleContainerTest.php @@ -26,6 +26,7 @@ namespace Test\AppFramework\Utility; use OC\AppFramework\Utility\SimpleContainer; +use Psr\Container\NotFoundExceptionInterface; interface TestInterface { } @@ -76,11 +77,31 @@ public function testRegister() { } - + /** + * Test querying a class that is not registered without autoload enabled + */ public function testNothingRegistered() { - $this->expectException(\OCP\AppFramework\QueryException::class); + try { + $this->container->query('something really hard', false); + $this->fail('Expected `QueryException` exception was not thrown'); + } catch (\Throwable $exception) { + $this->assertInstanceOf(\OCP\AppFramework\QueryException::class, $exception); + $this->assertInstanceOf(NotFoundExceptionInterface::class, $exception); + } + } + - $this->container->query('something really hard'); + /** + * Test querying a class that is not registered with autoload enabled + */ + public function testNothingRegistered_autoload() { + try { + $this->container->query('something really hard'); + $this->fail('Expected `QueryException` exception was not thrown'); + } catch (\Throwable $exception) { + $this->assertInstanceOf(\OCP\AppFramework\QueryException::class, $exception); + $this->assertInstanceOf(NotFoundExceptionInterface::class, $exception); + } } From 43589312ccbdf977bb6d89eae3bec28bde2dceff Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 6 Feb 2023 18:16:23 +0100 Subject: [PATCH 05/59] dont delegate Mount\Manager::getByNumericId to getByStorageId Signed-off-by: Robin Appelman --- lib/private/Files/Mount/Manager.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php index 9ba0e50405880..805cce658a678 100644 --- a/lib/private/Files/Mount/Manager.php +++ b/lib/private/Files/Mount/Manager.php @@ -184,8 +184,13 @@ public function getAll(): array { * @return IMountPoint[] */ public function findByNumericId(int $id): array { - $storageId = \OC\Files\Cache\Storage::getStorageId($id); - return $this->findByStorageId($storageId); + $result = []; + foreach ($this->mounts as $mount) { + if ($mount->getNumericStorageId() === $id) { + $result[] = $mount; + } + } + return $result; } /** From 9281359fa47b5b67d09b0661bdfb0dcee9795b54 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 6 Feb 2023 18:17:40 +0100 Subject: [PATCH 06/59] deduplicate getStorage() logic in Mount\Manager Signed-off-by: Robin Appelman --- lib/private/Files/Mount/MountPoint.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/private/Files/Mount/MountPoint.php b/lib/private/Files/Mount/MountPoint.php index 49f7e560ad373..770655fae5061 100644 --- a/lib/private/Files/Mount/MountPoint.php +++ b/lib/private/Files/Mount/MountPoint.php @@ -199,15 +199,7 @@ public function getStorage() { */ public function getStorageId() { if (!$this->storageId) { - if (is_null($this->storage)) { - $storage = $this->createStorage(); //FIXME: start using exceptions - if (is_null($storage)) { - return null; - } - - $this->storage = $storage; - } - $this->storageId = $this->storage->getId(); + $this->storageId = $this->getStorage()->getId(); if (strlen($this->storageId) > 64) { $this->storageId = md5($this->storageId); } From e3bafcc7a813f6adb305c2e35057b925c278d4bd Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 6 Feb 2023 18:20:08 +0100 Subject: [PATCH 07/59] cache numeric id in mountpoint Signed-off-by: Robin Appelman --- lib/private/Files/Mount/MountPoint.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/private/Files/Mount/MountPoint.php b/lib/private/Files/Mount/MountPoint.php index 770655fae5061..67601f016be7c 100644 --- a/lib/private/Files/Mount/MountPoint.php +++ b/lib/private/Files/Mount/MountPoint.php @@ -44,6 +44,7 @@ class MountPoint implements IMountPoint { protected $storage = null; protected $class; protected $storageId; + protected $numericStorageId = null; protected $rootId = null; /** @@ -211,7 +212,10 @@ public function getStorageId() { * @return int */ public function getNumericStorageId() { - return $this->getStorage()->getStorageCache()->getNumericId(); + if (is_null($this->numericStorageId)) { + $this->numericStorageId = $this->getStorage()->getStorageCache()->getNumericId(); + } + return $this->numericStorageId; } /** From b55c62c6c22dcf5b3bf942f526bfb580c537b9d3 Mon Sep 17 00:00:00 2001 From: Mattia Narducci Date: Thu, 30 Sep 2021 20:06:49 +0200 Subject: [PATCH 08/59] dav: fix birthday calendar event generation for leap days Fix generation of birthday calendar events for the 29th of February. A recurring event for the 29th of February in the (default) Gregorian calendar system would only generate instances in leap years. Fix this behaviour by generating recurring events for the last day of February, the 29th on leap years and the 28th otherwise. Signed-off-by: Mattia Narducci --- apps/dav/lib/CalDAV/BirthdayService.php | 48 +++++++------- .../unit/CardDAV/BirthdayServiceTest.php | 64 ++++++++++--------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/apps/dav/lib/CalDAV/BirthdayService.php b/apps/dav/lib/CalDAV/BirthdayService.php index df351a475524a..70b2e859f89a4 100644 --- a/apps/dav/lib/CalDAV/BirthdayService.php +++ b/apps/dav/lib/CalDAV/BirthdayService.php @@ -207,33 +207,26 @@ public function buildDateFromContact(string $cardData, } catch (InvalidDataException $e) { return null; } + if ($dateParts['year'] !== null) { + $parameters = $birthday->parameters(); + $omitYear = (isset($parameters['X-APPLE-OMIT-YEAR']) + && $parameters['X-APPLE-OMIT-YEAR'] === $dateParts['year']); + // 'X-APPLE-OMIT-YEAR' is not always present, at least iOS 12.4 uses the hard coded date of 1604 (the start of the gregorian calendar) when the year is unknown + if ($omitYear || (int)$dateParts['year'] === 1604) { + $dateParts['year'] = null; + } + } - $unknownYear = false; $originalYear = null; - if (!$dateParts['year']) { - $birthday = '1970-' . $dateParts['month'] . '-' . $dateParts['date']; + if ($dateParts['year'] !== null) { + $originalYear = (int)$dateParts['year']; + } - $unknownYear = true; - } else { - $parameters = $birthday->parameters(); - if (isset($parameters['X-APPLE-OMIT-YEAR'])) { - $omitYear = $parameters['X-APPLE-OMIT-YEAR']; - if ($dateParts['year'] === $omitYear) { - $birthday = '1970-' . $dateParts['month'] . '-' . $dateParts['date']; - $unknownYear = true; - } - } else { - $originalYear = (int)$dateParts['year']; - // 'X-APPLE-OMIT-YEAR' is not always present, at least iOS 12.4 uses the hard coded date of 1604 (the start of the gregorian calendar) when the year is unknown - if ($originalYear == 1604) { - $originalYear = null; - $unknownYear = true; - $birthday = '1970-' . $dateParts['month'] . '-' . $dateParts['date']; - } - if ($originalYear < 1970) { - $birthday = '1970-' . $dateParts['month'] . '-' . $dateParts['date']; - } - } + $leapDay = ((int)$dateParts['month'] === 2 + && (int)$dateParts['date'] === 29); + if ($dateParts['year'] === null || $originalYear < 1970) { + $birthday = ($leapDay ? '1972-' : '1970-') + . $dateParts['month'] . '-' . $dateParts['date']; } try { @@ -268,10 +261,15 @@ public function buildDateFromContact(string $cardData, $vEvent->DTEND['VALUE'] = 'DATE'; $vEvent->{'UID'} = $doc->UID . $postfix; $vEvent->{'RRULE'} = 'FREQ=YEARLY'; + if ($leapDay) { + /* Sabre\VObject supports BYMONTHDAY only if BYMONTH + * is also set */ + $vEvent->{'RRULE'} = 'FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=-1'; + } $vEvent->{'SUMMARY'} = $summary; $vEvent->{'TRANSP'} = 'TRANSPARENT'; $vEvent->{'X-NEXTCLOUD-BC-FIELD-TYPE'} = $dateField; - $vEvent->{'X-NEXTCLOUD-BC-UNKNOWN-YEAR'} = $unknownYear ? '1' : '0'; + $vEvent->{'X-NEXTCLOUD-BC-UNKNOWN-YEAR'} = $dateParts['year'] === null ? '1' : '0'; if ($originalYear !== null) { $vEvent->{'X-NEXTCLOUD-BC-YEAR'} = (string) $originalYear; } diff --git a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php index 6cca861f6cca9..c3e27bf3dc9a6 100644 --- a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php +++ b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php @@ -78,13 +78,14 @@ protected function setUp(): void { * @dataProvider providesVCards * @param string $expectedSummary * @param string $expectedDTStart + * @param string $expectedRrule * @param string $expectedFieldType * @param string $expectedUnknownYear * @param string $expectedOriginalYear * @param string|null $expectedReminder * @param string | null $data */ - public function testBuildBirthdayFromContact($expectedSummary, $expectedDTStart, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Bytes, $configuredReminder): void { + public function testBuildBirthdayFromContact($expectedSummary, $expectedDTStart, $expectedRrule, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Bytes, $configuredReminder): void { $this->dbConnection->method('supports4ByteText')->willReturn($supports4Bytes); $cal = $this->service->buildDateFromContact($data, $fieldType, $prefix, $configuredReminder); @@ -94,7 +95,7 @@ public function testBuildBirthdayFromContact($expectedSummary, $expectedDTStart, $this->assertInstanceOf('Sabre\VObject\Component\VCalendar', $cal); $this->assertEquals('-//IDN nextcloud.com//Birthday calendar//EN', $cal->PRODID->getValue()); $this->assertTrue(isset($cal->VEVENT)); - $this->assertEquals('FREQ=YEARLY', $cal->VEVENT->RRULE->getValue()); + $this->assertEquals($expectedRrule, $cal->VEVENT->RRULE->getValue()); $this->assertEquals($expectedSummary, $cal->VEVENT->SUMMARY->getValue()); $this->assertEquals($expectedDTStart, $cal->VEVENT->DTSTART->getValue()); $this->assertEquals($expectedFieldType, $cal->VEVENT->{'X-NEXTCLOUD-BC-FIELD-TYPE'}->getValue()); @@ -410,35 +411,36 @@ public function providesCardChanges() { public function providesVCards() { return [ - // $expectedSummary, $expectedDTStart, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Byte, $configuredReminder - [null, null, null, null, null, null, 'yasfewf', '', '', true, null], - [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:someday\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - ['🎂 12345 (1900)', '19700101', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - ['🎂 12345 (1900)', '19701231', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - ['Death of 12345 (1900)', '19701231', 'DEATHDATE', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', true, null], - ['Death of 12345 (1900)', '19701231', 'DEATHDATE', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', false, null], - ['💍 12345 (1900)', '19701231', 'ANNIVERSARY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', true, null], - ['12345 (⚭1900)', '19701231', 'ANNIVERSARY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', false, null], - ['🎂 12345', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - ['🎂 12345', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - ['🎂 12345 (900)', '19701231', 'BDAY', '0', '900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - ['12345 (*1900)', '19700101', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', false, null], - ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, null], - ['12345 *', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', false, null], - ['12345 *', '19701231', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', false, null], - [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', false, null], - [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', false, null], - ['12345 (*900)', '19701231', 'BDAY', '0', '900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', false, null], - ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', 'PT9H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, 'PT9H'], - ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', '-PT15H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, '-PT15H'], - ['12345 (*1900)', '19701231', 'BDAY', '0', '1900', '-P6DT15H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, '-P6DT15H'], - [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nEND:VCARD\r\n", 'BDAY', '', true, null], - [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', true, null], - [null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', true, null], + // $expectedSummary, $expectedDTStart, $expectedRrule, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Byte, $configuredReminder + [null, null, null, null, null, null, null, 'yasfewf', '', '', true, null], + [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:someday\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + ['🎂 12345 (1900)', '19700101', 'FREQ=YEARLY', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + ['🎂 12345 (1900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + ['Death of 12345 (1900)', '19701231', 'FREQ=YEARLY', 'DEATHDATE', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', true, null], + ['Death of 12345 (1900)', '19701231', 'FREQ=YEARLY', 'DEATHDATE', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', false, null], + ['💍 12345 (1900)', '19701231', 'FREQ=YEARLY', 'ANNIVERSARY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', true, null], + ['12345 (⚭1900)', '19701231', 'FREQ=YEARLY', 'ANNIVERSARY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', false, null], + ['🎂 12345', '19701231', 'FREQ=YEARLY', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + ['🎂 12345', '19701231', 'FREQ=YEARLY', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + ['🎂 12345 (900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + ['12345 (*1900)', '19700101', 'FREQ=YEARLY', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", 'BDAY', '', false, null], + ['12345 (*1900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '1900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, null], + ['12345 *', '19701231', 'FREQ=YEARLY', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", 'BDAY', '', false, null], + ['12345 *', '19701231', 'FREQ=YEARLY', 'BDAY', '1', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", 'BDAY', '', false, null], + [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", 'BDAY', '', false, null], + [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", 'BDAY', '', false, null], + ['12345 (*900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '900', null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", 'BDAY', '', false, null], + ['12345 (*1900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '1900', 'PT9H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, 'PT9H'], + ['12345 (*1900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '1900', '-PT15H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, '-PT15H'], + ['12345 (*1900)', '19701231', 'FREQ=YEARLY', 'BDAY', '0', '1900', '-P6DT15H', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", 'BDAY', '', false, '-P6DT15H'], + [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nEND:VCARD\r\n", 'BDAY', '', true, null], + [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nDEATHDATE:19001231\r\nEND:VCARD\r\n", 'DEATHDATE', '-death', true, null], + [null, null, null, null, null, null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nANNIVERSARY:19001231\r\nX-NC-EXCLUDE-FROM-BIRTHDAY-CALENDAR;TYPE=boolean:true\r\nEND:VCARD\r\n", 'ANNIVERSARY', '-anniversary', true, null], + ['🎂 12345 (1902)', '19720229', 'FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=-1', 'BDAY', '0', null, null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19020229\r\nEND:VCARD\r\n", 'BDAY', '', true, null], ]; } } From 4b867bb7bbaabac62bd19f191fea7d069763787e Mon Sep 17 00:00:00 2001 From: Christopher Ng Date: Mon, 6 Feb 2023 17:34:12 -0800 Subject: [PATCH 09/59] Port profile visibility select Signed-off-by: Christopher Ng --- .../VisibilityDropdown.vue | 17 ++++++++--------- dist/settings-vue-settings-personal-info.js | 4 ++-- dist/settings-vue-settings-personal-info.js.map | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/VisibilityDropdown.vue b/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/VisibilityDropdown.vue index 24f025f2da09a..f00130ec0a454 100644 --- a/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/VisibilityDropdown.vue +++ b/apps/settings/src/components/PersonalInfo/ProfileVisibilitySection/VisibilityDropdown.vue @@ -26,13 +26,12 @@ - + @option:selected="onVisibilityChange" /> @@ -41,7 +40,7 @@ import { showError } from '@nextcloud/dialogs' import { loadState } from '@nextcloud/initial-state' import { subscribe, unsubscribe } from '@nextcloud/event-bus' -import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect' +import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js' import { saveProfileParameterVisibility } from '../../../service/ProfileService.js' import { VISIBILITY_PROPERTY_ENUM } from '../../../constants/ProfileConstants.js' @@ -53,7 +52,7 @@ export default { name: 'VisibilityDropdown', components: { - NcMultiselect, + NcSelect, }, props: { @@ -173,8 +172,8 @@ export default { line-height: 50px; } - &__multiselect { - width: 260px; + &__select { + width: 270px; max-width: 40vw; } } diff --git a/dist/settings-vue-settings-personal-info.js b/dist/settings-vue-settings-personal-info.js index 9e09da01da650..42d8437f7f5ff 100644 --- a/dist/settings-vue-settings-personal-info.js +++ b/dist/settings-vue-settings-personal-info.js @@ -1,3 +1,3 @@ /*! For license information please see settings-vue-settings-personal-info.js.LICENSE.txt */ -!function(){var e,n={3491:function(e,n,r){"use strict";var a=r(20144),i=r(45994),o=r(79954),s=r(31352),l=(r(36144),r(4820)),c=r(79753),u=r(26932),p=r(78595),d=r(75925),f=r.n(d),A=r(10861),m=r.n(A),v=r(17652),g=(r(74063),r(75762)),b=r(34829),y=r(57612),h=r(61149),C=r(12945),x=r.n(C),w=r(45400),E={name:"FederationControlAction",components:{NcActionButton:r.n(w)()},props:{activeScope:{type:String,required:!0},displayName:{type:String,required:!0},handleScopeChange:{type:Function,default:function(){}},iconClass:{type:String,required:!0},isSupportedScope:{type:Boolean,required:!0},name:{type:String,required:!0},tooltipDisabled:{type:String,default:""},tooltip:{type:String,required:!0}},methods:{updateScope:function(){this.handleScopeChange(this.name)}}},P=r(93379),S=r.n(P),_=r(7795),O=r.n(_),j=r(90569),I=r.n(j),k=r(3565),L=r.n(k),D=r(19216),R=r.n(D),B=r(44589),T=r.n(B),N=r(8915),Z={};Z.styleTagTransform=T(),Z.setAttributes=L(),Z.insert=I().bind(null,"head"),Z.domAPI=O(),Z.insertStyleElement=R(),S()(N.Z,Z),N.Z&&N.Z.locals&&N.Z.locals;var M,U,F,z,V=r(51900),H=(0,V.Z)(E,(function(){var t=this;return(0,t._self._c)("NcActionButton",{staticClass:"federation-actions__btn",class:{"federation-actions__btn--active":t.activeScope===t.name},attrs:{"aria-label":t.isSupportedScope?t.tooltip:t.tooltipDisabled,"close-after-click":!0,disabled:!t.isSupportedScope,icon:t.iconClass,title:t.isSupportedScope?t.tooltip:t.tooltipDisabled},on:{click:function(e){return e.stopPropagation(),e.preventDefault(),t.updateScope.apply(null,arguments)}}},[t._v("\n\t"+t._s(t.isSupportedScope?t.tooltip:t.tooltipDisabled)+"\n")])}),[],!1,null,"2dff160a",null),G=H.exports;function q(t){return q="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},q(t)}function Y(t,e,n){return(e=function(t){var e=function(t,e){if("object"!==q(t)||null===t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var r=n.call(t,e);if("object"!==q(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t,"string");return"symbol"===q(e)?e:String(e)}(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var $=Object.freeze({ADDRESS:"address",AVATAR:"avatar",BIOGRAPHY:"biography",DISPLAYNAME:"displayname",EMAIL_COLLECTION:"additional_mail",EMAIL:"email",HEADLINE:"headline",NOTIFICATION_EMAIL:"notify_email",FEDIVERSE:"fediverse",ORGANISATION:"organisation",PHONE:"phone",PROFILE_ENABLED:"profile_enabled",ROLE:"role",TWITTER:"twitter",WEBSITE:"website"}),W=Object.freeze({ADDRESS:(0,s.Iu)("settings","Location"),AVATAR:(0,s.Iu)("settings","Profile picture"),BIOGRAPHY:(0,s.Iu)("settings","About"),DISPLAYNAME:(0,s.Iu)("settings","Full name"),EMAIL_COLLECTION:(0,s.Iu)("settings","Additional email"),EMAIL:(0,s.Iu)("settings","Email"),HEADLINE:(0,s.Iu)("settings","Headline"),ORGANISATION:(0,s.Iu)("settings","Organisation"),PHONE:(0,s.Iu)("settings","Phone number"),PROFILE_ENABLED:(0,s.Iu)("settings","Profile"),ROLE:(0,s.Iu)("settings","Role"),TWITTER:(0,s.Iu)("settings","Twitter"),FEDIVERSE:(0,s.Iu)("settings","Fediverse (e.g. Mastodon)"),WEBSITE:(0,s.Iu)("settings","Website")}),K=Object.freeze((Y(M={},$.ADDRESS,W.ADDRESS),Y(M,$.AVATAR,W.AVATAR),Y(M,$.BIOGRAPHY,W.BIOGRAPHY),Y(M,$.DISPLAYNAME,W.DISPLAYNAME),Y(M,$.EMAIL_COLLECTION,W.EMAIL_COLLECTION),Y(M,$.EMAIL,W.EMAIL),Y(M,$.HEADLINE,W.HEADLINE),Y(M,$.ORGANISATION,W.ORGANISATION),Y(M,$.PHONE,W.PHONE),Y(M,$.PROFILE_ENABLED,W.PROFILE_ENABLED),Y(M,$.ROLE,W.ROLE),Y(M,$.TWITTER,W.TWITTER),Y(M,$.FEDIVERSE,W.FEDIVERSE),Y(M,$.WEBSITE,W.WEBSITE),M)),Q=Object.freeze({PROFILE_VISIBILITY:(0,s.Iu)("settings","Profile visibility")}),X=Object.freeze((Y(U={},W.ADDRESS,$.ADDRESS),Y(U,W.AVATAR,$.AVATAR),Y(U,W.BIOGRAPHY,$.BIOGRAPHY),Y(U,W.DISPLAYNAME,$.DISPLAYNAME),Y(U,W.EMAIL_COLLECTION,$.EMAIL_COLLECTION),Y(U,W.EMAIL,$.EMAIL),Y(U,W.HEADLINE,$.HEADLINE),Y(U,W.ORGANISATION,$.ORGANISATION),Y(U,W.PHONE,$.PHONE),Y(U,W.PROFILE_ENABLED,$.PROFILE_ENABLED),Y(U,W.ROLE,$.ROLE),Y(U,W.TWITTER,$.TWITTER),Y(U,W.FEDIVERSE,$.FEDIVERSE),Y(U,W.WEBSITE,$.WEBSITE),U)),J=Object.freeze({LANGUAGE:"language",LOCALE:"locale"}),tt=Object.freeze({LANGUAGE:(0,s.Iu)("settings","Language"),LOCALE:(0,s.Iu)("settings","Locale")}),et=Object.freeze({PRIVATE:"v2-private",LOCAL:"v2-local",FEDERATED:"v2-federated",PUBLISHED:"v2-published"}),nt=Object.freeze((Y(F={},W.ADDRESS,[et.LOCAL,et.PRIVATE]),Y(F,W.AVATAR,[et.LOCAL,et.PRIVATE]),Y(F,W.BIOGRAPHY,[et.LOCAL,et.PRIVATE]),Y(F,W.DISPLAYNAME,[et.LOCAL]),Y(F,W.EMAIL_COLLECTION,[et.LOCAL]),Y(F,W.EMAIL,[et.LOCAL]),Y(F,W.HEADLINE,[et.LOCAL,et.PRIVATE]),Y(F,W.ORGANISATION,[et.LOCAL,et.PRIVATE]),Y(F,W.PHONE,[et.LOCAL,et.PRIVATE]),Y(F,W.PROFILE_ENABLED,[et.LOCAL,et.PRIVATE]),Y(F,W.ROLE,[et.LOCAL,et.PRIVATE]),Y(F,W.TWITTER,[et.LOCAL,et.PRIVATE]),Y(F,W.FEDIVERSE,[et.LOCAL,et.PRIVATE]),Y(F,W.WEBSITE,[et.LOCAL,et.PRIVATE]),F)),rt=Object.freeze([W.BIOGRAPHY,W.HEADLINE,W.ORGANISATION,W.ROLE]),at="Scope",it=Object.freeze((Y(z={},et.PRIVATE,{name:et.PRIVATE,displayName:(0,s.Iu)("settings","Private"),tooltip:(0,s.Iu)("settings","Only visible to people matched via phone number integration through Talk on mobile"),tooltipDisabled:(0,s.Iu)("settings","Not available as this property is required for core functionality including file sharing and calendar invitations"),iconClass:"icon-phone"}),Y(z,et.LOCAL,{name:et.LOCAL,displayName:(0,s.Iu)("settings","Local"),tooltip:(0,s.Iu)("settings","Only visible to people on this instance and guests"),iconClass:"icon-password"}),Y(z,et.FEDERATED,{name:et.FEDERATED,displayName:(0,s.Iu)("settings","Federated"),tooltip:(0,s.Iu)("settings","Only synchronize to trusted servers"),tooltipDisabled:(0,s.Iu)("settings","Not available as federation has been disabled for your account, contact your system administrator if you have any questions"),iconClass:"icon-contacts-dark"}),Y(z,et.PUBLISHED,{name:et.PUBLISHED,displayName:(0,s.Iu)("settings","Published"),tooltip:(0,s.Iu)("settings","Synchronize to trusted servers and the global and public address book"),tooltipDisabled:(0,s.Iu)("settings","Not available as publishing user specific data to the lookup server is not allowed, contact your system administrator if you have any questions"),iconClass:"icon-link"}),z)),ot=et.LOCAL,st=Object.freeze({NOT_VERIFIED:0,VERIFICATION_IN_PROGRESS:1,VERIFIED:2}),lt=/^(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){255,})(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){65,}@)(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22))(?:\.(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\]))$/i,ct=r(10128);function ut(t,e,n,r,a,i,o){try{var s=t[i](o),l=s.value}catch(t){return void n(t)}s.done?e(l):Promise.resolve(l).then(r,a)}function pt(t){return function(){var e=this,n=arguments;return new Promise((function(r,a){var i=t.apply(e,n);function o(t){ut(i,r,a,o,s,"next",t)}function s(t){ut(i,r,a,o,s,"throw",t)}o(void 0)}))}}r(65509);var dt=function(){var t=pt(regeneratorRuntime.mark((function t(e,n){var r,a,o;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return"boolean"==typeof n&&(n=n?"1":"0"),r=(0,i.ts)().uid,a=(0,c.generateOcsUrl)("cloud/users/{userId}",{userId:r}),t.next=5,(0,ct.confirmPassword)();case 5:return t.next=7,l.default.put(a,{key:e,value:n});case 7:return o=t.sent,t.abrupt("return",o.data);case 9:case"end":return t.stop()}}),t)})));return function(e,n){return t.apply(this,arguments)}}(),ft=function(){var t=pt(regeneratorRuntime.mark((function t(e,n){var r,a,o;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=(0,i.ts)().uid,a=(0,c.generateOcsUrl)("cloud/users/{userId}",{userId:r}),t.next=4,(0,ct.confirmPassword)();case 4:return t.next=6,l.default.put(a,{key:"".concat(e).concat(at),value:n});case 6:return o=t.sent,t.abrupt("return",o.data);case 8:case"end":return t.stop()}}),t)})));return function(e,n){return t.apply(this,arguments)}}(),At=(0,r(17499).IY)().setApp("settings").detectUser().build();function mt(t,e,n,r,a,i,o){try{var s=t[i](o),l=s.value}catch(t){return void n(t)}s.done?e(l):Promise.resolve(l).then(r,a)}function vt(t){return function(){var e=this,n=arguments;return new Promise((function(r,a){var i=t.apply(e,n);function o(t){mt(i,r,a,o,s,"next",t)}function s(t){mt(i,r,a,o,s,"throw",t)}o(void 0)}))}}var gt=(0,o.j)("settings","accountParameters",{}),bt=gt.federationEnabled,yt=gt.lookupServerUploadEnabled,ht={name:"FederationControl",components:{NcActions:x(),FederationControlAction:G},props:{readable:{type:String,required:!0,validator:function(t){return Object.values(W).includes(t)||Object.values(tt).includes(t)||t===Q.PROFILE_VISIBILITY}},additional:{type:Boolean,default:!1},additionalValue:{type:String,default:""},disabled:{type:Boolean,default:!1},handleAdditionalScopeChange:{type:Function,default:null},scope:{type:String,required:!0}},data:function(){return{readableLowerCase:this.readable.toLocaleLowerCase(),initialScope:this.scope}},computed:{ariaLabel:function(){return t("settings","Change scope level of {property}, current scope is {scope}",{property:this.readableLowerCase,scope:this.scopeDisplayNameLowerCase})},scopeDisplayNameLowerCase:function(){return it[this.scope].displayName.toLocaleLowerCase()},scopeIcon:function(){return it[this.scope].iconClass},federationScopes:function(){return Object.values(it)},supportedScopes:function(){var t=nt[this.readable];return rt.includes(this.readable)||(bt&&t.push(et.FEDERATED),yt&&t.push(et.PUBLISHED)),t}},methods:{changeScope:function(t){var e=this;return vt(regeneratorRuntime.mark((function n(){return regeneratorRuntime.wrap((function(n){for(;;)switch(n.prev=n.next){case 0:if(e.$emit("update:scope",t),e.additional){n.next=6;break}return n.next=4,e.updatePrimaryScope(t);case 4:n.next=8;break;case 6:return n.next=8,e.updateAdditionalScope(t);case 8:case"end":return n.stop()}}),n)})))()},updatePrimaryScope:function(e){var n=this;return vt(regeneratorRuntime.mark((function r(){var a,i,o;return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:return r.prev=0,r.next=3,ft(X[n.readable],e);case 3:o=r.sent,n.handleResponse({scope:e,status:null===(a=o.ocs)||void 0===a||null===(i=a.meta)||void 0===i?void 0:i.status}),r.next=10;break;case 7:r.prev=7,r.t0=r.catch(0),n.handleResponse({errorMessage:t("settings","Unable to update federation scope of the primary {property}",{property:n.readableLowerCase}),error:r.t0});case 10:case"end":return r.stop()}}),r,null,[[0,7]])})))()},updateAdditionalScope:function(e){var n=this;return vt(regeneratorRuntime.mark((function r(){var a,i,o;return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:return r.prev=0,r.next=3,n.handleAdditionalScopeChange(n.additionalValue,e);case 3:o=r.sent,n.handleResponse({scope:e,status:null===(a=o.ocs)||void 0===a||null===(i=a.meta)||void 0===i?void 0:i.status}),r.next=10;break;case 7:r.prev=7,r.t0=r.catch(0),n.handleResponse({errorMessage:t("settings","Unable to update federation scope of additional {property}",{property:n.readableLowerCase}),error:r.t0});case 10:case"end":return r.stop()}}),r,null,[[0,7]])})))()},handleResponse:function(t){var e=t.scope,n=t.status,r=t.errorMessage,a=t.error;"ok"===n?this.initialScope=e:(this.$emit("update:scope",this.initialScope),(0,u.x2)(r),At.error(r,a))}}},Ct=r(59003),xt={};xt.styleTagTransform=T(),xt.setAttributes=L(),xt.insert=I().bind(null,"head"),xt.domAPI=O(),xt.insertStyleElement=R(),S()(Ct.Z,xt),Ct.Z&&Ct.Z.locals&&Ct.Z.locals;var wt=(0,V.Z)(ht,(function(){var t=this,e=t._self._c;return e("NcActions",{class:{"federation-actions":!t.additional,"federation-actions--additional":t.additional},attrs:{"aria-label":t.ariaLabel,"default-icon":t.scopeIcon,disabled:t.disabled}},t._l(t.federationScopes,(function(n){return e("FederationControlAction",{key:n.name,attrs:{"active-scope":t.scope,"display-name":n.displayName,"handle-scope-change":t.changeScope,"icon-class":n.iconClass,"is-supported-scope":t.supportedScopes.includes(n.name),name:n.name,"tooltip-disabled":n.tooltipDisabled,tooltip:n.tooltip,"aria-label":n.tooltip}})})),1)}),[],!1,null,"2513166c",null).exports,Et={name:"HeaderBar",components:{FederationControl:wt,NcButton:m(),Plus:h.Z},props:{scope:{type:String,default:null},readable:{type:String,required:!0},inputId:{type:String,default:null},isEditable:{type:Boolean,default:!0},isMultiValueSupported:{type:Boolean,default:!1},isValidSection:{type:Boolean,default:!0}},data:function(){return{localScope:this.scope}},computed:{isProfileProperty:function(){return this.readable===W.PROFILE_ENABLED},isSettingProperty:function(){return!Object.values(W).includes(this.readable)&&!Object.values(Q).includes(this.readable)}},methods:{onAddAdditional:function(){this.$emit("add-additional")},onScopeChange:function(t){this.$emit("update:scope",t)}}},Pt=r(37684),St={};St.styleTagTransform=T(),St.setAttributes=L(),St.insert=I().bind(null,"head"),St.domAPI=O(),St.insertStyleElement=R(),S()(Pt.Z,St),Pt.Z&&Pt.Z.locals&&Pt.Z.locals;var _t=(0,V.Z)(Et,(function(){var t=this,e=t._self._c;return e("h3",{class:{"setting-property":t.isSettingProperty,"profile-property":t.isProfileProperty}},[e("label",{attrs:{for:t.inputId}},[t._v("\n\t\t"+t._s(t.readable)+"\n\t")]),t._v(" "),t.scope?[e("FederationControl",{staticClass:"federation-control",attrs:{readable:t.readable,scope:t.localScope},on:{"update:scope":[function(e){t.localScope=e},t.onScopeChange]}})]:t._e(),t._v(" "),t.isEditable&&t.isMultiValueSupported?[e("NcButton",{attrs:{type:"tertiary",disabled:!t.isValidSection,"aria-label":t.t("settings","Add additional email")},on:{click:function(e){return e.stopPropagation(),e.preventDefault(),t.onAddAdditional.apply(null,arguments)}},scopedSlots:t._u([{key:"icon",fn:function(){return[e("Plus",{attrs:{size:20}})]},proxy:!0}],null,!1,32235154)},[t._v("\n\t\t\t"+t._s(t.t("settings","Add"))+"\n\t\t")])]:t._e()],2)}),[],!1,null,"8094b2e6",null),Ot=_t.exports;function jt(t){return jt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},jt(t)}function It(t,e,n,r,a,i,o){try{var s=t[i](o),l=s.value}catch(t){return void n(t)}s.done?e(l):Promise.resolve(l).then(r,a)}function kt(t){return function(){var e=this,n=arguments;return new Promise((function(r,a){var i=t.apply(e,n);function o(t){It(i,r,a,o,s,"next",t)}function s(t){It(i,r,a,o,s,"throw",t)}o(void 0)}))}}function Lt(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function Dt(t){for(var e=1;e{usage}",{usage:Xt}):t("settings","You are using {usage} of {totalSpace} ({usageRelative}%)",{usage:Xt,totalSpace:Qt,usageRelative:Jt})}},data:function(){return{groups:Wt,usageRelative:Jt}}},ee=r(94122),ne={};ne.styleTagTransform=T(),ne.setAttributes=L(),ne.insert=I().bind(null,"head"),ne.domAPI=O(),ne.insertStyleElement=R(),S()(ee.Z,ne),ee.Z&&ee.Z.locals&&ee.Z.locals;var re=(0,V.Z)(te,(function(){var t=this,e=t._self._c;return e("section",[e("HeaderBar",{attrs:{readable:t.t("settings","Details")}}),t._v(" "),e("div",{staticClass:"details"},[e("div",{staticClass:"details__groups"},[e("Account",{attrs:{size:20}}),t._v(" "),e("div",{staticClass:"details__groups-info"},[e("p",[t._v(t._s(t.t("settings","You are a member of the following groups:")))]),t._v(" "),e("p",{staticClass:"details__groups-list"},[t._v(t._s(t.groups.join(", ")))])])],1),t._v(" "),e("div",{staticClass:"details__quota"},[e("CircleSlice",{attrs:{size:20}}),t._v(" "),e("div",{staticClass:"details__quota-info"},[e("p",{staticClass:"details__quota-text",domProps:{innerHTML:t._s(t.quotaText)}}),t._v(" "),e("NcProgressBar",{attrs:{size:"medium",value:t.usageRelative,error:t.usageRelative>80}})],1)],1)])],1)}),[],!1,null,"546e7ece",null).exports,ae=r(20296),ie=r.n(ae),oe=r(94603),se=r(31974),le=r(80419);function ce(t,e,n,r,a,i,o){try{var s=t[i](o),l=s.value}catch(t){return void n(t)}s.done?e(l):Promise.resolve(l).then(r,a)}function ue(t){return function(){var e=this,n=arguments;return new Promise((function(r,a){var i=t.apply(e,n);function o(t){ce(i,r,a,o,s,"next",t)}function s(t){ce(i,r,a,o,s,"throw",t)}o(void 0)}))}}var pe={name:"AccountPropertySection",components:{AlertCircle:oe.default,AlertOctagon:se.Z,Check:le.default,HeaderBar:Ot},props:{name:{type:String,required:!0},value:{type:String,required:!0},scope:{type:String,required:!0},readable:{type:String,required:!0},placeholder:{type:String,required:!0},type:{type:String,default:"text"},isEditable:{type:Boolean,default:!0},multiLine:{type:Boolean,default:!1},onValidate:{type:Function,default:null},onSave:{type:Function,default:null}},data:function(){return{initialValue:this.value,helperText:null,showCheckmarkIcon:!1,showErrorIcon:!1}},computed:{inputId:function(){return"account-property-".concat(this.name)}},methods:{onPropertyChange:function(t){this.$emit("update:value",t.target.value),this.debouncePropertyChange(t.target.value.trim())},debouncePropertyChange:ie()(function(){var t=ue(regeneratorRuntime.mark((function t(e){return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(this.helperText=null,!this.$refs.input||!this.$refs.input.validationMessage){t.next=4;break}return this.helperText=this.$refs.input.validationMessage,t.abrupt("return");case 4:if(!this.onValidate||this.onValidate(e)){t.next=6;break}return t.abrupt("return");case 6:return t.next=8,this.updateProperty(e);case 8:case"end":return t.stop()}}),t,this)})));return function(e){return t.apply(this,arguments)}}(),500),updateProperty:function(e){var n=this;return ue(regeneratorRuntime.mark((function r(){var a,i,o;return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:return r.prev=0,r.next=3,dt(n.name,e);case 3:o=r.sent,n.handleResponse({value:e,status:null===(a=o.ocs)||void 0===a||null===(i=a.meta)||void 0===i?void 0:i.status}),r.next=10;break;case 7:r.prev=7,r.t0=r.catch(0),n.handleResponse({errorMessage:t("settings","Unable to update {property}",{property:n.readable.toLocaleLowerCase()}),error:r.t0});case 10:case"end":return r.stop()}}),r,null,[[0,7]])})))()},handleResponse:function(t){var e=this,n=t.value,r=t.status,a=t.errorMessage,i=t.error;"ok"===r?(this.initialValue=n,this.onSave&&this.onSave(n),this.showCheckmarkIcon=!0,setTimeout((function(){e.showCheckmarkIcon=!1}),2e3)):(this.$emit("update:value",this.initialValue),(0,u.x2)(a),At.error(a,i),this.showErrorIcon=!0,setTimeout((function(){e.showErrorIcon=!1}),2e3))}}},de=pe,fe=r(69728),Ae={};Ae.styleTagTransform=T(),Ae.setAttributes=L(),Ae.insert=I().bind(null,"head"),Ae.domAPI=O(),Ae.insertStyleElement=R(),S()(fe.Z,Ae),fe.Z&&fe.Z.locals&&fe.Z.locals;var me=(0,V.Z)(de,(function(){var t=this,e=t._self._c;return e("section",[e("HeaderBar",{attrs:{scope:t.scope,readable:t.readable,"input-id":t.inputId,"is-editable":t.isEditable},on:{"update:scope":function(e){t.scope=e},"update:readable":function(e){t.readable=e}}}),t._v(" "),t.isEditable?e("div",{staticClass:"property"},[t.multiLine?e("textarea",{attrs:{id:t.inputId,placeholder:t.placeholder,rows:"8",autocapitalize:"none",autocomplete:"off",autocorrect:"off"},domProps:{value:t.value},on:{input:t.onPropertyChange}}):e("input",{ref:"input",attrs:{id:t.inputId,placeholder:t.placeholder,type:t.type,"aria-describedby":t.helperText?"".concat(t.name,"-helper-text"):"",autocapitalize:"none",autocomplete:"on",autocorrect:"off"},domProps:{value:t.value},on:{input:t.onPropertyChange}}),t._v(" "),e("div",{staticClass:"property__actions-container"},[e("transition",{attrs:{name:"fade"}},[t.showCheckmarkIcon?e("Check",{attrs:{size:20}}):t.showErrorIcon?e("AlertOctagon",{attrs:{size:20}}):t._e()],1)],1)]):e("span",[t._v("\n\t\t"+t._s(t.value||t.t("settings","No {property} set",{property:t.readable.toLocaleLowerCase()}))+"\n\t")]),t._v(" "),t.helperText?e("p",{staticClass:"property__helper-text-message property__helper-text-message--error",attrs:{id:"".concat(t.name,"-helper-text")}},[e("AlertCircle",{staticClass:"property__helper-text-message__icon",attrs:{size:18}}),t._v("\n\t\t"+t._s(t.helperText)+"\n\t")],1):t._e()],1)}),[],!1,null,"2943fbd4",null).exports;function ve(t){return ve="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},ve(t)}function ge(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function be(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);nt.length)&&(e=t.length);for(var n=0,r=new Array(e);nt.length)&&(e=t.length);for(var n=0,r=new Array(e);n=i)&&Object.keys(a.O).every((function(t){return a.O[t](n[l])}))?n.splice(l--,1):(s=!1,i0&&e[u-1][2]>i;u--)e[u]=e[u-1];e[u]=[n,r,i]},a.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return a.d(e,{a:e}),e},a.d=function(t,e){for(var n in e)a.o(e,n)&&!a.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),a.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},a.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},a.nmd=function(t){return t.paths=[],t.children||(t.children=[]),t},a.j=4418,function(){a.b=document.baseURI||self.location.href;var t={4418:0};a.O.j=function(e){return 0===t[e]};var e=function(e,n){var r,i,o=n[0],s=n[1],l=n[2],c=0;if(o.some((function(e){return 0!==t[e]}))){for(r in s)a.o(s,r)&&(a.m[r]=s[r]);if(l)var u=l(a)}for(e&&e(n);c{usage}",{usage:Xt}):t("settings","You are using {usage} of {totalSpace} ({usageRelative}%)",{usage:Xt,totalSpace:Qt,usageRelative:Jt})}},data:function(){return{groups:Wt,usageRelative:Jt}}},ee=r(94122),ne={};ne.styleTagTransform=T(),ne.setAttributes=L(),ne.insert=I().bind(null,"head"),ne.domAPI=O(),ne.insertStyleElement=R(),S()(ee.Z,ne),ee.Z&&ee.Z.locals&&ee.Z.locals;var re=(0,V.Z)(te,(function(){var t=this,e=t._self._c;return e("section",[e("HeaderBar",{attrs:{readable:t.t("settings","Details")}}),t._v(" "),e("div",{staticClass:"details"},[e("div",{staticClass:"details__groups"},[e("Account",{attrs:{size:20}}),t._v(" "),e("div",{staticClass:"details__groups-info"},[e("p",[t._v(t._s(t.t("settings","You are a member of the following groups:")))]),t._v(" "),e("p",{staticClass:"details__groups-list"},[t._v(t._s(t.groups.join(", ")))])])],1),t._v(" "),e("div",{staticClass:"details__quota"},[e("CircleSlice",{attrs:{size:20}}),t._v(" "),e("div",{staticClass:"details__quota-info"},[e("p",{staticClass:"details__quota-text",domProps:{innerHTML:t._s(t.quotaText)}}),t._v(" "),e("NcProgressBar",{attrs:{size:"medium",value:t.usageRelative,error:t.usageRelative>80}})],1)],1)])],1)}),[],!1,null,"546e7ece",null).exports,ae=r(20296),ie=r.n(ae),oe=r(94603),se=r(31974),le=r(80419);function ce(t,e,n,r,a,i,o){try{var s=t[i](o),l=s.value}catch(t){return void n(t)}s.done?e(l):Promise.resolve(l).then(r,a)}function ue(t){return function(){var e=this,n=arguments;return new Promise((function(r,a){var i=t.apply(e,n);function o(t){ce(i,r,a,o,s,"next",t)}function s(t){ce(i,r,a,o,s,"throw",t)}o(void 0)}))}}var pe={name:"AccountPropertySection",components:{AlertCircle:oe.default,AlertOctagon:se.Z,Check:le.default,HeaderBar:Ot},props:{name:{type:String,required:!0},value:{type:String,required:!0},scope:{type:String,required:!0},readable:{type:String,required:!0},placeholder:{type:String,required:!0},type:{type:String,default:"text"},isEditable:{type:Boolean,default:!0},multiLine:{type:Boolean,default:!1},onValidate:{type:Function,default:null},onSave:{type:Function,default:null}},data:function(){return{initialValue:this.value,helperText:null,showCheckmarkIcon:!1,showErrorIcon:!1}},computed:{inputId:function(){return"account-property-".concat(this.name)}},methods:{onPropertyChange:function(t){this.$emit("update:value",t.target.value),this.debouncePropertyChange(t.target.value.trim())},debouncePropertyChange:ie()(function(){var t=ue(regeneratorRuntime.mark((function t(e){return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(this.helperText=null,!this.$refs.input||!this.$refs.input.validationMessage){t.next=4;break}return this.helperText=this.$refs.input.validationMessage,t.abrupt("return");case 4:if(!this.onValidate||this.onValidate(e)){t.next=6;break}return t.abrupt("return");case 6:return t.next=8,this.updateProperty(e);case 8:case"end":return t.stop()}}),t,this)})));return function(e){return t.apply(this,arguments)}}(),500),updateProperty:function(e){var n=this;return ue(regeneratorRuntime.mark((function r(){var a,i,o;return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:return r.prev=0,r.next=3,dt(n.name,e);case 3:o=r.sent,n.handleResponse({value:e,status:null===(a=o.ocs)||void 0===a||null===(i=a.meta)||void 0===i?void 0:i.status}),r.next=10;break;case 7:r.prev=7,r.t0=r.catch(0),n.handleResponse({errorMessage:t("settings","Unable to update {property}",{property:n.readable.toLocaleLowerCase()}),error:r.t0});case 10:case"end":return r.stop()}}),r,null,[[0,7]])})))()},handleResponse:function(t){var e=this,n=t.value,r=t.status,a=t.errorMessage,i=t.error;"ok"===r?(this.initialValue=n,this.onSave&&this.onSave(n),this.showCheckmarkIcon=!0,setTimeout((function(){e.showCheckmarkIcon=!1}),2e3)):(this.$emit("update:value",this.initialValue),(0,u.x2)(a),At.error(a,i),this.showErrorIcon=!0,setTimeout((function(){e.showErrorIcon=!1}),2e3))}}},de=pe,fe=r(69728),Ae={};Ae.styleTagTransform=T(),Ae.setAttributes=L(),Ae.insert=I().bind(null,"head"),Ae.domAPI=O(),Ae.insertStyleElement=R(),S()(fe.Z,Ae),fe.Z&&fe.Z.locals&&fe.Z.locals;var me=(0,V.Z)(de,(function(){var t=this,e=t._self._c;return e("section",[e("HeaderBar",{attrs:{scope:t.scope,readable:t.readable,"input-id":t.inputId,"is-editable":t.isEditable},on:{"update:scope":function(e){t.scope=e},"update:readable":function(e){t.readable=e}}}),t._v(" "),t.isEditable?e("div",{staticClass:"property"},[t.multiLine?e("textarea",{attrs:{id:t.inputId,placeholder:t.placeholder,rows:"8",autocapitalize:"none",autocomplete:"off",autocorrect:"off"},domProps:{value:t.value},on:{input:t.onPropertyChange}}):e("input",{ref:"input",attrs:{id:t.inputId,placeholder:t.placeholder,type:t.type,"aria-describedby":t.helperText?"".concat(t.name,"-helper-text"):"",autocapitalize:"none",autocomplete:"on",autocorrect:"off"},domProps:{value:t.value},on:{input:t.onPropertyChange}}),t._v(" "),e("div",{staticClass:"property__actions-container"},[e("transition",{attrs:{name:"fade"}},[t.showCheckmarkIcon?e("Check",{attrs:{size:20}}):t.showErrorIcon?e("AlertOctagon",{attrs:{size:20}}):t._e()],1)],1)]):e("span",[t._v("\n\t\t"+t._s(t.value||t.t("settings","No {property} set",{property:t.readable.toLocaleLowerCase()}))+"\n\t")]),t._v(" "),t.helperText?e("p",{staticClass:"property__helper-text-message property__helper-text-message--error",attrs:{id:"".concat(t.name,"-helper-text")}},[e("AlertCircle",{staticClass:"property__helper-text-message__icon",attrs:{size:18}}),t._v("\n\t\t"+t._s(t.helperText)+"\n\t")],1):t._e()],1)}),[],!1,null,"2943fbd4",null).exports;function ve(t){return ve="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},ve(t)}function ge(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function be(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);nt.length)&&(e=t.length);for(var n=0,r=new Array(e);nt.length)&&(e=t.length);for(var n=0,r=new Array(e);n=i)&&Object.keys(a.O).every((function(t){return a.O[t](n[l])}))?n.splice(l--,1):(s=!1,i0&&e[u-1][2]>i;u--)e[u]=e[u-1];e[u]=[n,r,i]},a.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return a.d(e,{a:e}),e},a.d=function(t,e){for(var n in e)a.o(e,n)&&!a.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),a.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},a.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},a.nmd=function(t){return t.paths=[],t.children||(t.children=[]),t},a.j=4418,function(){a.b=document.baseURI||self.location.href;var t={4418:0};a.O.j=function(e){return 0===t[e]};var e=function(e,n){var r,i,o=n[0],s=n[1],l=n[2],c=0;if(o.some((function(e){return 0!==t[e]}))){for(r in s)a.o(s,r)&&(a.m[r]=s[r]);if(l)var u=l(a)}for(e&&e(n);c 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(function(key) { return __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};","import mod from \"-!../../../../../../node_modules/babel-loader/lib/index.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FederationControlAction.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../../../node_modules/babel-loader/lib/index.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FederationControlAction.vue?vue&type=script&lang=js&\"","\n\n\n\n\n\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/vue-loader/lib/loaders/stylePostLoader.js!../../../../../../node_modules/sass-loader/dist/cjs.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FederationControlAction.vue?vue&type=style&index=0&id=2dff160a&prod&lang=scss&scoped=true&\";\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/vue-loader/lib/loaders/stylePostLoader.js!../../../../../../node_modules/sass-loader/dist/cjs.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FederationControlAction.vue?vue&type=style&index=0&id=2dff160a&prod&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./FederationControlAction.vue?vue&type=template&id=2dff160a&scoped=true&\"\nimport script from \"./FederationControlAction.vue?vue&type=script&lang=js&\"\nexport * from \"./FederationControlAction.vue?vue&type=script&lang=js&\"\nimport style0 from \"./FederationControlAction.vue?vue&type=style&index=0&id=2dff160a&prod&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"2dff160a\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('NcActionButton',{staticClass:\"federation-actions__btn\",class:{ 'federation-actions__btn--active': _vm.activeScope === _vm.name },attrs:{\"aria-label\":_vm.isSupportedScope ? _vm.tooltip : _vm.tooltipDisabled,\"close-after-click\":true,\"disabled\":!_vm.isSupportedScope,\"icon\":_vm.iconClass,\"title\":_vm.isSupportedScope ? _vm.tooltip : _vm.tooltipDisabled},on:{\"click\":function($event){$event.stopPropagation();$event.preventDefault();return _vm.updateScope.apply(null, arguments)}}},[_vm._v(\"\\n\\t\"+_vm._s(_vm.isSupportedScope ? _vm.tooltip : _vm.tooltipDisabled)+\"\\n\")])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","/**\n * @copyright 2021, Christopher Ng \n *\n * @author Christopher Ng \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 .\n *\n */\n\n/*\n * SYNC to be kept in sync with `lib/public/Accounts/IAccountManager.php`\n */\n\nimport { translate as t } from '@nextcloud/l10n'\n\n/** Enum of account properties */\nexport const ACCOUNT_PROPERTY_ENUM = Object.freeze({\n\tADDRESS: 'address',\n\tAVATAR: 'avatar',\n\tBIOGRAPHY: 'biography',\n\tDISPLAYNAME: 'displayname',\n\tEMAIL_COLLECTION: 'additional_mail',\n\tEMAIL: 'email',\n\tHEADLINE: 'headline',\n\tNOTIFICATION_EMAIL: 'notify_email',\n\tFEDIVERSE: 'fediverse',\n\tORGANISATION: 'organisation',\n\tPHONE: 'phone',\n\tPROFILE_ENABLED: 'profile_enabled',\n\tROLE: 'role',\n\tTWITTER: 'twitter',\n\tWEBSITE: 'website',\n})\n\n/** Enum of account properties to human readable account property names */\nexport const ACCOUNT_PROPERTY_READABLE_ENUM = Object.freeze({\n\tADDRESS: t('settings', 'Location'),\n\tAVATAR: t('settings', 'Profile picture'),\n\tBIOGRAPHY: t('settings', 'About'),\n\tDISPLAYNAME: t('settings', 'Full name'),\n\tEMAIL_COLLECTION: t('settings', 'Additional email'),\n\tEMAIL: t('settings', 'Email'),\n\tHEADLINE: t('settings', 'Headline'),\n\tORGANISATION: t('settings', 'Organisation'),\n\tPHONE: t('settings', 'Phone number'),\n\tPROFILE_ENABLED: t('settings', 'Profile'),\n\tROLE: t('settings', 'Role'),\n\tTWITTER: t('settings', 'Twitter'),\n\tFEDIVERSE: t('settings', 'Fediverse (e.g. Mastodon)'),\n\tWEBSITE: t('settings', 'Website'),\n})\n\nexport const NAME_READABLE_ENUM = Object.freeze({\n\t[ACCOUNT_PROPERTY_ENUM.ADDRESS]: ACCOUNT_PROPERTY_READABLE_ENUM.ADDRESS,\n\t[ACCOUNT_PROPERTY_ENUM.AVATAR]: ACCOUNT_PROPERTY_READABLE_ENUM.AVATAR,\n\t[ACCOUNT_PROPERTY_ENUM.BIOGRAPHY]: ACCOUNT_PROPERTY_READABLE_ENUM.BIOGRAPHY,\n\t[ACCOUNT_PROPERTY_ENUM.DISPLAYNAME]: ACCOUNT_PROPERTY_READABLE_ENUM.DISPLAYNAME,\n\t[ACCOUNT_PROPERTY_ENUM.EMAIL_COLLECTION]: ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL_COLLECTION,\n\t[ACCOUNT_PROPERTY_ENUM.EMAIL]: ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL,\n\t[ACCOUNT_PROPERTY_ENUM.HEADLINE]: ACCOUNT_PROPERTY_READABLE_ENUM.HEADLINE,\n\t[ACCOUNT_PROPERTY_ENUM.ORGANISATION]: ACCOUNT_PROPERTY_READABLE_ENUM.ORGANISATION,\n\t[ACCOUNT_PROPERTY_ENUM.PHONE]: ACCOUNT_PROPERTY_READABLE_ENUM.PHONE,\n\t[ACCOUNT_PROPERTY_ENUM.PROFILE_ENABLED]: ACCOUNT_PROPERTY_READABLE_ENUM.PROFILE_ENABLED,\n\t[ACCOUNT_PROPERTY_ENUM.ROLE]: ACCOUNT_PROPERTY_READABLE_ENUM.ROLE,\n\t[ACCOUNT_PROPERTY_ENUM.TWITTER]: ACCOUNT_PROPERTY_READABLE_ENUM.TWITTER,\n\t[ACCOUNT_PROPERTY_ENUM.FEDIVERSE]: ACCOUNT_PROPERTY_READABLE_ENUM.FEDIVERSE,\n\t[ACCOUNT_PROPERTY_ENUM.WEBSITE]: ACCOUNT_PROPERTY_READABLE_ENUM.WEBSITE,\n})\n\n/** Enum of profile specific sections to human readable names */\nexport const PROFILE_READABLE_ENUM = Object.freeze({\n\tPROFILE_VISIBILITY: t('settings', 'Profile visibility'),\n})\n\n/** Enum of readable account properties to account property keys used by the server */\nexport const PROPERTY_READABLE_KEYS_ENUM = Object.freeze({\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.ADDRESS]: ACCOUNT_PROPERTY_ENUM.ADDRESS,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.AVATAR]: ACCOUNT_PROPERTY_ENUM.AVATAR,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.BIOGRAPHY]: ACCOUNT_PROPERTY_ENUM.BIOGRAPHY,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.DISPLAYNAME]: ACCOUNT_PROPERTY_ENUM.DISPLAYNAME,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL_COLLECTION]: ACCOUNT_PROPERTY_ENUM.EMAIL_COLLECTION,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL]: ACCOUNT_PROPERTY_ENUM.EMAIL,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.HEADLINE]: ACCOUNT_PROPERTY_ENUM.HEADLINE,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.ORGANISATION]: ACCOUNT_PROPERTY_ENUM.ORGANISATION,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.PHONE]: ACCOUNT_PROPERTY_ENUM.PHONE,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.PROFILE_ENABLED]: ACCOUNT_PROPERTY_ENUM.PROFILE_ENABLED,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.ROLE]: ACCOUNT_PROPERTY_ENUM.ROLE,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.TWITTER]: ACCOUNT_PROPERTY_ENUM.TWITTER,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.FEDIVERSE]: ACCOUNT_PROPERTY_ENUM.FEDIVERSE,\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.WEBSITE]: ACCOUNT_PROPERTY_ENUM.WEBSITE,\n})\n\n/**\n * Enum of account setting properties\n *\n * Account setting properties unlike account properties do not support scopes*\n */\nexport const ACCOUNT_SETTING_PROPERTY_ENUM = Object.freeze({\n\tLANGUAGE: 'language',\n\tLOCALE: 'locale',\n})\n\n/** Enum of account setting properties to human readable setting properties */\nexport const ACCOUNT_SETTING_PROPERTY_READABLE_ENUM = Object.freeze({\n\tLANGUAGE: t('settings', 'Language'),\n\tLOCALE: t('settings', 'Locale'),\n})\n\n/** Enum of scopes */\nexport const SCOPE_ENUM = Object.freeze({\n\tPRIVATE: 'v2-private',\n\tLOCAL: 'v2-local',\n\tFEDERATED: 'v2-federated',\n\tPUBLISHED: 'v2-published',\n})\n\n/** Enum of readable account properties to supported scopes */\nexport const PROPERTY_READABLE_SUPPORTED_SCOPES_ENUM = Object.freeze({\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.ADDRESS]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.AVATAR]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.BIOGRAPHY]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.DISPLAYNAME]: [SCOPE_ENUM.LOCAL],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL_COLLECTION]: [SCOPE_ENUM.LOCAL],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.EMAIL]: [SCOPE_ENUM.LOCAL],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.HEADLINE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.ORGANISATION]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.PHONE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.PROFILE_ENABLED]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.ROLE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.TWITTER]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.FEDIVERSE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n\t[ACCOUNT_PROPERTY_READABLE_ENUM.WEBSITE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],\n})\n\n/** List of readable account properties which aren't published to the lookup server */\nexport const UNPUBLISHED_READABLE_PROPERTIES = Object.freeze([\n\tACCOUNT_PROPERTY_READABLE_ENUM.BIOGRAPHY,\n\tACCOUNT_PROPERTY_READABLE_ENUM.HEADLINE,\n\tACCOUNT_PROPERTY_READABLE_ENUM.ORGANISATION,\n\tACCOUNT_PROPERTY_READABLE_ENUM.ROLE,\n])\n\n/** Scope suffix */\nexport const SCOPE_SUFFIX = 'Scope'\n\n/**\n * Enum of scope names to properties\n *\n * Used for federation control*\n */\nexport const SCOPE_PROPERTY_ENUM = Object.freeze({\n\t[SCOPE_ENUM.PRIVATE]: {\n\t\tname: SCOPE_ENUM.PRIVATE,\n\t\tdisplayName: t('settings', 'Private'),\n\t\ttooltip: t('settings', 'Only visible to people matched via phone number integration through Talk on mobile'),\n\t\ttooltipDisabled: t('settings', 'Not available as this property is required for core functionality including file sharing and calendar invitations'),\n\t\ticonClass: 'icon-phone',\n\t},\n\t[SCOPE_ENUM.LOCAL]: {\n\t\tname: SCOPE_ENUM.LOCAL,\n\t\tdisplayName: t('settings', 'Local'),\n\t\ttooltip: t('settings', 'Only visible to people on this instance and guests'),\n\t\t// tooltipDisabled is not required here as this scope is supported by all account properties\n\t\ticonClass: 'icon-password',\n\t},\n\t[SCOPE_ENUM.FEDERATED]: {\n\t\tname: SCOPE_ENUM.FEDERATED,\n\t\tdisplayName: t('settings', 'Federated'),\n\t\ttooltip: t('settings', 'Only synchronize to trusted servers'),\n\t\ttooltipDisabled: t('settings', 'Not available as federation has been disabled for your account, contact your system administrator if you have any questions'),\n\t\ticonClass: 'icon-contacts-dark',\n\t},\n\t[SCOPE_ENUM.PUBLISHED]: {\n\t\tname: SCOPE_ENUM.PUBLISHED,\n\t\tdisplayName: t('settings', 'Published'),\n\t\ttooltip: t('settings', 'Synchronize to trusted servers and the global and public address book'),\n\t\ttooltipDisabled: t('settings', 'Not available as publishing user specific data to the lookup server is not allowed, contact your system administrator if you have any questions'),\n\t\ticonClass: 'icon-link',\n\t},\n})\n\n/** Default additional email scope */\nexport const DEFAULT_ADDITIONAL_EMAIL_SCOPE = SCOPE_ENUM.LOCAL\n\n/** Enum of verification constants, according to IAccountManager */\nexport const VERIFICATION_ENUM = Object.freeze({\n\tNOT_VERIFIED: 0,\n\tVERIFICATION_IN_PROGRESS: 1,\n\tVERIFIED: 2,\n})\n\n/**\n * Email validation regex\n *\n * Sourced from https://github.com/mpyw/FILTER_VALIDATE_EMAIL.js/blob/71e62ca48841d2246a1b531e7e84f5a01f15e615/src/regexp/ascii.ts*\n */\n// eslint-disable-next-line no-control-regex\nexport const VALIDATE_EMAIL_REGEX = /^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/i\n","/**\n * @copyright 2021, Christopher Ng \n *\n * @author Christopher Ng \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 .\n *\n */\n\nimport axios from '@nextcloud/axios'\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { generateOcsUrl } from '@nextcloud/router'\nimport { confirmPassword } from '@nextcloud/password-confirmation'\nimport '@nextcloud/password-confirmation/dist/style.css'\n\nimport { SCOPE_SUFFIX } from '../../constants/AccountPropertyConstants'\n\n/**\n * Save the primary account property value for the user\n *\n * @param {string} accountProperty the account property\n * @param {string|boolean} value the primary value\n * @return {object}\n */\nexport const savePrimaryAccountProperty = async (accountProperty, value) => {\n\t// TODO allow boolean values on backend route handler\n\t// Convert boolean to string for compatibility\n\tif (typeof value === 'boolean') {\n\t\tvalue = value ? '1' : '0'\n\t}\n\n\tconst userId = getCurrentUser().uid\n\tconst url = generateOcsUrl('cloud/users/{userId}', { userId })\n\n\tawait confirmPassword()\n\n\tconst res = await axios.put(url, {\n\t\tkey: accountProperty,\n\t\tvalue,\n\t})\n\n\treturn res.data\n}\n\n/**\n * Save the federation scope of the primary account property for the user\n *\n * @param {string} accountProperty the account property\n * @param {string} scope the federation scope\n * @return {object}\n */\nexport const savePrimaryAccountPropertyScope = async (accountProperty, scope) => {\n\tconst userId = getCurrentUser().uid\n\tconst url = generateOcsUrl('cloud/users/{userId}', { userId })\n\n\tawait confirmPassword()\n\n\tconst res = await axios.put(url, {\n\t\tkey: `${accountProperty}${SCOPE_SUFFIX}`,\n\t\tvalue: scope,\n\t})\n\n\treturn res.data\n}\n","/**\n * @copyright 2020 Christoph Wurst \n *\n * @author Roeland Jago Douma \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 .\n *\n */\n\nimport { getLoggerBuilder } from '@nextcloud/logger'\n\nexport default getLoggerBuilder()\n\t.setApp('settings')\n\t.detectUser()\n\t.build()\n","\n\n\n\n\n\n\n","import mod from \"-!../../../../../../node_modules/babel-loader/lib/index.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FederationControl.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../../../node_modules/babel-loader/lib/index.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FederationControl.vue?vue&type=script&lang=js&\"","\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/vue-loader/lib/loaders/stylePostLoader.js!../../../../../../node_modules/sass-loader/dist/cjs.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FederationControl.vue?vue&type=style&index=0&id=2513166c&prod&lang=scss&scoped=true&\";\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/vue-loader/lib/loaders/stylePostLoader.js!../../../../../../node_modules/sass-loader/dist/cjs.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FederationControl.vue?vue&type=style&index=0&id=2513166c&prod&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./FederationControl.vue?vue&type=template&id=2513166c&scoped=true&\"\nimport script from \"./FederationControl.vue?vue&type=script&lang=js&\"\nexport * from \"./FederationControl.vue?vue&type=script&lang=js&\"\nimport style0 from \"./FederationControl.vue?vue&type=style&index=0&id=2513166c&prod&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"2513166c\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('NcActions',{class:{ 'federation-actions': !_vm.additional, 'federation-actions--additional': _vm.additional },attrs:{\"aria-label\":_vm.ariaLabel,\"default-icon\":_vm.scopeIcon,\"disabled\":_vm.disabled}},_vm._l((_vm.federationScopes),function(federationScope){return _c('FederationControlAction',{key:federationScope.name,attrs:{\"active-scope\":_vm.scope,\"display-name\":federationScope.displayName,\"handle-scope-change\":_vm.changeScope,\"icon-class\":federationScope.iconClass,\"is-supported-scope\":_vm.supportedScopes.includes(federationScope.name),\"name\":federationScope.name,\"tooltip-disabled\":federationScope.tooltipDisabled,\"tooltip\":federationScope.tooltip,\"aria-label\":federationScope.tooltip}})}),1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../../../../node_modules/babel-loader/lib/index.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HeaderBar.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../../../node_modules/babel-loader/lib/index.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HeaderBar.vue?vue&type=script&lang=js&\"","\n\n\n\n\n\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/vue-loader/lib/loaders/stylePostLoader.js!../../../../../../node_modules/sass-loader/dist/cjs.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HeaderBar.vue?vue&type=style&index=0&id=8094b2e6&prod&lang=scss&scoped=true&\";\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/vue-loader/lib/loaders/stylePostLoader.js!../../../../../../node_modules/sass-loader/dist/cjs.js!../../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HeaderBar.vue?vue&type=style&index=0&id=8094b2e6&prod&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./HeaderBar.vue?vue&type=template&id=8094b2e6&scoped=true&\"\nimport script from \"./HeaderBar.vue?vue&type=script&lang=js&\"\nexport * from \"./HeaderBar.vue?vue&type=script&lang=js&\"\nimport style0 from \"./HeaderBar.vue?vue&type=style&index=0&id=8094b2e6&prod&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"8094b2e6\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('h3',{class:{ 'setting-property': _vm.isSettingProperty, 'profile-property': _vm.isProfileProperty }},[_c('label',{attrs:{\"for\":_vm.inputId}},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.readable)+\"\\n\\t\")]),_vm._v(\" \"),(_vm.scope)?[_c('FederationControl',{staticClass:\"federation-control\",attrs:{\"readable\":_vm.readable,\"scope\":_vm.localScope},on:{\"update:scope\":[function($event){_vm.localScope=$event},_vm.onScopeChange]}})]:_vm._e(),_vm._v(\" \"),(_vm.isEditable && _vm.isMultiValueSupported)?[_c('NcButton',{attrs:{\"type\":\"tertiary\",\"disabled\":!_vm.isValidSection,\"aria-label\":_vm.t('settings', 'Add additional email')},on:{\"click\":function($event){$event.stopPropagation();$event.preventDefault();return _vm.onAddAdditional.apply(null, arguments)}},scopedSlots:_vm._u([{key:\"icon\",fn:function(){return [_c('Plus',{attrs:{\"size\":20}})]},proxy:true}],null,false,32235154)},[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.t('settings', 'Add'))+\"\\n\\t\\t\")])]:_vm._e()],2)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n","import mod from \"-!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AvatarSection.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AvatarSection.vue?vue&type=script&lang=js&\"","\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/vue-loader/lib/loaders/stylePostLoader.js!../../../../../node_modules/sass-loader/dist/cjs.js!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AvatarSection.vue?vue&type=style&index=0&id=53d0771f&prod&lang=scss&scoped=true&\";\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/vue-loader/lib/loaders/stylePostLoader.js!../../../../../node_modules/sass-loader/dist/cjs.js!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AvatarSection.vue?vue&type=style&index=0&id=53d0771f&prod&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./AvatarSection.vue?vue&type=template&id=53d0771f&scoped=true&\"\nimport script from \"./AvatarSection.vue?vue&type=script&lang=js&\"\nexport * from \"./AvatarSection.vue?vue&type=script&lang=js&\"\nimport style0 from \"./AvatarSection.vue?vue&type=style&index=0&id=53d0771f&prod&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"53d0771f\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('section',{attrs:{\"id\":\"vue-avatar-section\"}},[_c('HeaderBar',{attrs:{\"input-id\":_vm.avatarChangeSupported ? _vm.inputId : null,\"readable\":_vm.avatar.readable,\"scope\":_vm.avatar.scope},on:{\"update:scope\":function($event){return _vm.$set(_vm.avatar, \"scope\", $event)}}}),_vm._v(\" \"),(!_vm.showCropper)?_c('div',{staticClass:\"avatar__container\"},[_c('div',{staticClass:\"avatar__preview\"},[(!_vm.loading)?_c('NcAvatar',{key:_vm.version,attrs:{\"user\":_vm.userId,\"aria-label\":_vm.t('settings', 'Your profile picture'),\"disabled-menu\":true,\"disabled-tooltip\":true,\"show-user-status\":false,\"size\":180}}):_c('div',{staticClass:\"icon-loading\"})],1),_vm._v(\" \"),(_vm.avatarChangeSupported)?[_c('div',{staticClass:\"avatar__buttons\"},[_c('NcButton',{attrs:{\"aria-label\":_vm.t('settings', 'Upload profile picture')},on:{\"click\":_vm.activateLocalFilePicker},scopedSlots:_vm._u([{key:\"icon\",fn:function(){return [_c('Upload',{attrs:{\"size\":20}})]},proxy:true}],null,false,1329850251)}),_vm._v(\" \"),_c('NcButton',{attrs:{\"aria-label\":_vm.t('settings', 'Choose profile picture from files')},on:{\"click\":_vm.openFilePicker},scopedSlots:_vm._u([{key:\"icon\",fn:function(){return [_c('Folder',{attrs:{\"size\":20}})]},proxy:true}],null,false,4270628382)}),_vm._v(\" \"),(!_vm.isGenerated)?_c('NcButton',{attrs:{\"aria-label\":_vm.t('settings', 'Remove profile picture')},on:{\"click\":_vm.removeAvatar},scopedSlots:_vm._u([{key:\"icon\",fn:function(){return [_c('Delete',{attrs:{\"size\":20}})]},proxy:true}],null,false,2705356561)}):_vm._e()],1),_vm._v(\" \"),_c('span',[_vm._v(_vm._s(_vm.t('settings', 'png or jpg, max. 20 MB')))]),_vm._v(\" \"),_c('input',{ref:\"input\",attrs:{\"id\":_vm.inputId,\"type\":\"file\",\"accept\":_vm.validMimeTypes.join(',')},on:{\"change\":_vm.onChange}})]:_c('span',[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.t('settings', 'Picture provided by original account'))+\"\\n\\t\\t\")])],2):_vm._e(),_vm._v(\" \"),_c('div',{directives:[{name:\"show\",rawName:\"v-show\",value:(_vm.showCropper),expression:\"showCropper\"}],staticClass:\"avatar__container\"},[_c('VueCropper',_vm._b({ref:\"cropper\",staticClass:\"avatar__cropper\"},'VueCropper',_vm.cropperOptions,false)),_vm._v(\" \"),_c('div',{staticClass:\"avatar__cropper-buttons\"},[_c('NcButton',{on:{\"click\":_vm.cancel}},[_vm._v(\"\\n\\t\\t\\t\\t\"+_vm._s(_vm.t('settings', 'Cancel'))+\"\\n\\t\\t\\t\")]),_vm._v(\" \"),_c('NcButton',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.saveAvatar}},[_vm._v(\"\\n\\t\\t\\t\\t\"+_vm._s(_vm.t('settings', 'Set as profile picture'))+\"\\n\\t\\t\\t\")])],1),_vm._v(\" \"),_c('span',[_vm._v(_vm._s(_vm.t('settings', 'Please note that it can take up to 24 hours for your profile picture to be updated everywhere.')))])],1)],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n","import mod from \"-!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DetailsSection.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../../node_modules/babel-loader/lib/index.js!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DetailsSection.vue?vue&type=script&lang=js&\"","\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/vue-loader/lib/loaders/stylePostLoader.js!../../../../../node_modules/sass-loader/dist/cjs.js!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DetailsSection.vue?vue&type=style&index=0&id=546e7ece&prod&lang=scss&scoped=true&\";\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/vue-loader/lib/loaders/stylePostLoader.js!../../../../../node_modules/sass-loader/dist/cjs.js!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DetailsSection.vue?vue&type=style&index=0&id=546e7ece&prod&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./DetailsSection.vue?vue&type=template&id=546e7ece&scoped=true&\"\nimport script from \"./DetailsSection.vue?vue&type=script&lang=js&\"\nexport * from \"./DetailsSection.vue?vue&type=script&lang=js&\"\nimport style0 from \"./DetailsSection.vue?vue&type=style&index=0&id=546e7ece&prod&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"546e7ece\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('section',[_c('HeaderBar',{attrs:{\"readable\":_vm.t('settings', 'Details')}}),_vm._v(\" \"),_c('div',{staticClass:\"details\"},[_c('div',{staticClass:\"details__groups\"},[_c('Account',{attrs:{\"size\":20}}),_vm._v(\" \"),_c('div',{staticClass:\"details__groups-info\"},[_c('p',[_vm._v(_vm._s(_vm.t('settings', 'You are a member of the following groups:')))]),_vm._v(\" \"),_c('p',{staticClass:\"details__groups-list\"},[_vm._v(_vm._s(_vm.groups.join(', ')))])])],1),_vm._v(\" \"),_c('div',{staticClass:\"details__quota\"},[_c('CircleSlice',{attrs:{\"size\":20}}),_vm._v(\" \"),_c('div',{staticClass:\"details__quota-info\"},[_c('p',{staticClass:\"details__quota-text\",domProps:{\"innerHTML\":_vm._s(_vm.quotaText)}}),_vm._v(\" \"),_c('NcProgressBar',{attrs:{\"size\":\"medium\",\"value\":_vm.usageRelative,\"error\":_vm.usageRelative > 80}})],1)],1)])],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n