diff options
author | Carl Schwan <carl@carlschwan.eu> | 2022-09-02 12:05:51 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-02 12:05:51 +0200 |
commit | 2397ea72196de42a79e2a5873dcbb07db698f348 (patch) | |
tree | cfe0e7e4f6ec10a665eb0a40eae103bafc49203f /apps/settings/lib | |
parent | 046d5451b15d46581cde846676e0b6d631fedbb7 (diff) | |
parent | 30be6ad605f3e451c17de3df74ec3832e1758afe (diff) | |
download | nextcloud-server-2397ea72196de42a79e2a5873dcbb07db698f348.tar.gz nextcloud-server-2397ea72196de42a79e2a5873dcbb07db698f348.zip |
Merge branch 'master' into fix/setting/accessibility-title
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Diffstat (limited to 'apps/settings/lib')
-rw-r--r-- | apps/settings/lib/Activity/GroupProvider.php | 25 | ||||
-rw-r--r-- | apps/settings/lib/Activity/Provider.php | 18 | ||||
-rw-r--r-- | apps/settings/lib/Controller/AppSettingsController.php | 4 | ||||
-rw-r--r-- | apps/settings/lib/Controller/ChangePasswordController.php | 39 | ||||
-rw-r--r-- | apps/settings/lib/Controller/CheckSetupController.php | 17 | ||||
-rw-r--r-- | apps/settings/lib/Controller/CommonSettingsTrait.php | 7 | ||||
-rw-r--r-- | apps/settings/lib/Controller/HelpController.php | 2 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Delegation.php | 22 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Security.php | 44 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Server.php | 45 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Sharing.php | 2 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Personal/PersonalInfo.php | 132 | ||||
-rw-r--r-- | apps/settings/lib/SetupChecks/SupportedDatabase.php | 6 | ||||
-rw-r--r-- | apps/settings/lib/UserMigration/AccountMigrator.php | 57 |
14 files changed, 174 insertions, 246 deletions
diff --git a/apps/settings/lib/Activity/GroupProvider.php b/apps/settings/lib/Activity/GroupProvider.php index a1709de5c3f..466bb9abeee 100644 --- a/apps/settings/lib/Activity/GroupProvider.php +++ b/apps/settings/lib/Activity/GroupProvider.php @@ -51,8 +51,6 @@ class GroupProvider implements IProvider { /** @var string[] */ protected $groupDisplayNames = []; - /** @var string[] */ - protected $userDisplayNames = []; public function __construct(L10nFactory $l10n, @@ -169,32 +167,11 @@ class GroupProvider implements IProvider { return $gid; } - /** - * @param string $uid - * @return array - */ protected function generateUserParameter(string $uid): array { - if (!isset($this->displayNames[$uid])) { - $this->userDisplayNames[$uid] = $this->getDisplayName($uid); - } - return [ 'type' => 'user', 'id' => $uid, - 'name' => $this->userDisplayNames[$uid], + 'name' => $this->userManager->getDisplayName($uid) ?? $uid, ]; } - - /** - * @param string $uid - * @return string - */ - protected function getDisplayName(string $uid): string { - $user = $this->userManager->get($uid); - if ($user instanceof IUser) { - return $user->getDisplayName(); - } else { - return $uid; - } - } } diff --git a/apps/settings/lib/Activity/Provider.php b/apps/settings/lib/Activity/Provider.php index a6314fdfb11..7d8a7f0da9a 100644 --- a/apps/settings/lib/Activity/Provider.php +++ b/apps/settings/lib/Activity/Provider.php @@ -66,9 +66,6 @@ class Provider implements IProvider { /** @var IManager */ private $activityManager; - /** @var string[] cached displayNames - key is the UID and value the displayname */ - protected $displayNames = []; - public function __construct(IFactory $languageFactory, IURLGenerator $url, IUserManager $userManager, @@ -206,23 +203,10 @@ class Provider implements IProvider { } protected function generateUserParameter(string $uid): array { - if (!isset($this->displayNames[$uid])) { - $this->displayNames[$uid] = $this->getDisplayName($uid); - } - return [ 'type' => 'user', 'id' => $uid, - 'name' => $this->displayNames[$uid], + 'name' => $this->userManager->getDisplayName($uid) ?? $uid, ]; } - - protected function getDisplayName(string $uid): string { - $user = $this->userManager->get($uid); - if ($user instanceof IUser) { - return $user->getDisplayName(); - } - - return $uid; - } } diff --git a/apps/settings/lib/Controller/AppSettingsController.php b/apps/settings/lib/Controller/AppSettingsController.php index 77f807943cd..618d99b3d73 100644 --- a/apps/settings/lib/Controller/AppSettingsController.php +++ b/apps/settings/lib/Controller/AppSettingsController.php @@ -520,7 +520,7 @@ class AppSettingsController extends Controller { $this->appManager->clearAppsCache(); return new JSONResponse(['data' => ['appid' => $appId]]); } - return new JSONResponse(['data' => ['message' => $this->l10n->t('Couldn\'t remove app.')]], Http::STATUS_INTERNAL_SERVER_ERROR); + return new JSONResponse(['data' => ['message' => $this->l10n->t('Could not remove app.')]], Http::STATUS_INTERNAL_SERVER_ERROR); } /** @@ -542,7 +542,7 @@ class AppSettingsController extends Controller { if ($result !== false) { return new JSONResponse(['data' => ['appid' => $appId]]); } - return new JSONResponse(['data' => ['message' => $this->l10n->t('Couldn\'t update app.')]], Http::STATUS_INTERNAL_SERVER_ERROR); + return new JSONResponse(['data' => ['message' => $this->l10n->t('Could not update app.')]], Http::STATUS_INTERNAL_SERVER_ERROR); } private function sortApps($a, $b) { diff --git a/apps/settings/lib/Controller/ChangePasswordController.php b/apps/settings/lib/Controller/ChangePasswordController.php index 85e4218ebb5..a25f0b0e59b 100644 --- a/apps/settings/lib/Controller/ChangePasswordController.php +++ b/apps/settings/lib/Controller/ChangePasswordController.php @@ -49,28 +49,16 @@ use OCP\IUserManager; use OCP\IUserSession; class ChangePasswordController extends Controller { - - /** @var string */ - private $userId; - - /** @var IUserManager */ - private $userManager; - - /** @var IL10N */ - private $l; - - /** @var GroupManager */ - private $groupManager; - - /** @var Session */ - private $userSession; - - /** @var IAppManager */ - private $appManager; + private ?string $userId; + private IUserManager $userManager; + private IL10N $l; + private GroupManager $groupManager; + private Session $userSession; + private IAppManager $appManager; public function __construct(string $appName, IRequest $request, - string $userId, + ?string $userId, IUserManager $userManager, IUserSession $userSession, IGroupManager $groupManager, @@ -107,7 +95,7 @@ class ChangePasswordController extends Controller { } try { - if ($newpassword === null || $user->setPassword($newpassword) === false) { + if ($newpassword === null || strlen($newpassword) > 469 || $user->setPassword($newpassword) === false) { return new JSONResponse([ 'status' => 'error', 'data' => [ @@ -158,6 +146,15 @@ class ChangePasswordController extends Controller { ]); } + if (strlen($password) > 469) { + return new JSONResponse([ + 'status' => 'error', + 'data' => [ + 'message' => $this->l->t('Unable to change password. Password too long.'), + ], + ]); + } + $currentUser = $this->userSession->getUser(); $targetUser = $this->userManager->get($username); if ($currentUser === null || $targetUser === null || @@ -243,7 +240,7 @@ class ChangePasswordController extends Controller { return new JSONResponse([ 'status' => 'error', 'data' => [ - 'message' => $this->l->t('Backend doesn\'t support password change, but the user\'s encryption key was updated.'), + 'message' => $this->l->t('Backend does not support password change, but the user\'s encryption key was updated.'), ] ]); } elseif (!$result && !$recoveryEnabledForUser) { diff --git a/apps/settings/lib/Controller/CheckSetupController.php b/apps/settings/lib/Controller/CheckSetupController.php index 36532878922..8f469c6c4e9 100644 --- a/apps/settings/lib/Controller/CheckSetupController.php +++ b/apps/settings/lib/Controller/CheckSetupController.php @@ -317,7 +317,7 @@ class CheckSetupController extends Controller { 'app' => 'settings', 'exception' => $e, ]); - return $this->l10n->t('Could not determine if TLS version of cURL is outdated or not because an error happened during the HTTPS request against https://nextcloud.com. Please check the nextcloud log file for more details.'); + return $this->l10n->t('Could not determine if TLS version of cURL is outdated or not because an error happened during the HTTPS request against https://nextcloud.com. Please check the Nextcloud log file for more details.'); } } @@ -525,7 +525,11 @@ Raw output if ( empty($status['interned_strings_usage']['free_memory']) || - ($status['interned_strings_usage']['used_memory'] / $status['interned_strings_usage']['free_memory'] > 9) + ( + ($status['interned_strings_usage']['used_memory'] / $status['interned_strings_usage']['free_memory'] > 9) && + // Do not recommend to raise the interned strings buffer size above a quarter of the total OPcache size + ($this->iniGetWrapper->getNumeric('opcache.interned_strings_buffer') < $this->iniGetWrapper->getNumeric('opcache.memory_consumption') / 4) + ) ) { $recommendations[] = $this->l10n->t('The OPcache interned strings buffer is nearly full. To assure that repeating strings can be effectively cached, it is recommended to apply <code>opcache.interned_strings_buffer</code> to your PHP configuration with a value higher than <code>%s</code>.', [($this->iniGetWrapper->getNumeric('opcache.interned_strings_buffer') ?: 'currently')]); } @@ -743,6 +747,14 @@ Raw output return true; } + protected function is64bit(): bool { + if (PHP_INT_SIZE < 8) { + return false; + } else { + return true; + } + } + protected function isMysqlUsedWithoutUTF8MB4(): bool { return ($this->config->getSystemValue('dbtype', 'sqlite') === 'mysql') && ($this->config->getSystemValue('mysql.utf8mb4', false) === false); } @@ -876,6 +888,7 @@ Raw output 'appDirsWithDifferentOwner' => $this->getAppDirsWithDifferentOwner(), 'isImagickEnabled' => $this->isImagickEnabled(), 'areWebauthnExtensionsEnabled' => $this->areWebauthnExtensionsEnabled(), + 'is64bit' => $this->is64bit(), 'recommendedPHPModules' => $this->hasRecommendedPHPModules(), 'pendingBigIntConversionColumns' => $this->hasBigIntConversionPendingColumns(), 'isMysqlUsedWithoutUTF8MB4' => $this->isMysqlUsedWithoutUTF8MB4(), diff --git a/apps/settings/lib/Controller/CommonSettingsTrait.php b/apps/settings/lib/Controller/CommonSettingsTrait.php index 7cb706bb3a6..942d07154c4 100644 --- a/apps/settings/lib/Controller/CommonSettingsTrait.php +++ b/apps/settings/lib/Controller/CommonSettingsTrait.php @@ -134,7 +134,12 @@ trait CommonSettingsTrait { } private function getIndexResponse(string $type, string $section): TemplateResponse { - $this->navigationManager->setActiveEntry('settings'); + if ($type === 'personal') { + $this->navigationManager->setActiveEntry('settings'); + } elseif ($type === 'admin') { + $this->navigationManager->setActiveEntry('admin_settings'); + } + $templateParams = []; $templateParams = array_merge($templateParams, $this->getNavigationParameters($type, $section)); $templateParams = array_merge($templateParams, $this->getSettings($section)); diff --git a/apps/settings/lib/Controller/HelpController.php b/apps/settings/lib/Controller/HelpController.php index 8a62fb9b58c..b8780ae40ba 100644 --- a/apps/settings/lib/Controller/HelpController.php +++ b/apps/settings/lib/Controller/HelpController.php @@ -79,7 +79,7 @@ class HelpController extends Controller { } $documentationUrl = $this->urlGenerator->getAbsoluteURL( - $this->urlGenerator->linkTo('core', 'doc/' . $mode . '/index.html') + $this->urlGenerator->linkTo('', 'core/doc/' . $mode . '/index.html') ); $urlUserDocs = $this->urlGenerator->linkToRoute('settings.Help.help', ['mode' => 'user']); diff --git a/apps/settings/lib/Settings/Admin/Delegation.php b/apps/settings/lib/Settings/Admin/Delegation.php index 401d5b028cc..274b71150ed 100644 --- a/apps/settings/lib/Settings/Admin/Delegation.php +++ b/apps/settings/lib/Settings/Admin/Delegation.php @@ -31,30 +31,27 @@ use OCP\IGroupManager; use OCP\Settings\IDelegatedSettings; use OCP\Settings\IManager; use OCP\Settings\ISettings; +use OCP\IURLGenerator; class Delegation implements ISettings { - /** @var IManager */ - private $settingManager; - - /** @var IInitialState $initialStateService */ - private $initialStateService; - - /** @var IGroupManager $groupManager */ - private $groupManager; - - /** @var AuthorizedGroupService $authorizedGroupService */ - private $authorizedGroupService; + private IManager $settingManager; + private IInitialState $initialStateService; + private IGroupManager $groupManager; + private AuthorizedGroupService $authorizedGroupService; + private IURLGenerator $urlGenerator; public function __construct( IManager $settingManager, IInitialState $initialStateService, IGroupManager $groupManager, - AuthorizedGroupService $authorizedGroupService + AuthorizedGroupService $authorizedGroupService, + IURLGenerator $urlGenerator ) { $this->settingManager = $settingManager; $this->initialStateService = $initialStateService; $this->groupManager = $groupManager; $this->authorizedGroupService = $authorizedGroupService; + $this->urlGenerator = $urlGenerator; } /** @@ -128,6 +125,7 @@ class Delegation implements ISettings { $this->initSettingState(); $this->initAvailableGroupState(); $this->initAuthorizedGroupState(); + $this->initialStateService->provideInitialState('authorized-settings-doc-link', $this->urlGenerator->linkToDocs('admin-delegation')); return new TemplateResponse(Application::APP_ID, 'settings/admin/delegation', [], ''); } diff --git a/apps/settings/lib/Settings/Admin/Security.php b/apps/settings/lib/Settings/Admin/Security.php index 2580c0a3d00..63d3137a45c 100644 --- a/apps/settings/lib/Settings/Admin/Security.php +++ b/apps/settings/lib/Settings/Admin/Security.php @@ -31,30 +31,26 @@ use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; use OCP\Encryption\IManager; use OCP\IUserManager; +use OCP\IURLGenerator; use OCP\Settings\ISettings; class Security implements ISettings { - - /** @var IManager */ - private $manager; - - /** @var IUserManager */ - private $userManager; - - /** @var MandatoryTwoFactor */ - private $mandatoryTwoFactor; - - /** @var IInitialState */ - private $initialState; + private IManager $manager; + private IUserManager $userManager; + private MandatoryTwoFactor $mandatoryTwoFactor; + private IInitialState $initialState; + private IURLGenerator $urlGenerator; public function __construct(IManager $manager, IUserManager $userManager, MandatoryTwoFactor $mandatoryTwoFactor, - IInitialState $initialState) { + IInitialState $initialState, + IURLGenerator $urlGenerator) { $this->manager = $manager; $this->userManager = $userManager; $this->mandatoryTwoFactor = $mandatoryTwoFactor; $this->initialState = $initialState; + $this->urlGenerator = $urlGenerator; } /** @@ -72,21 +68,15 @@ class Security implements ISettings { } } - $this->initialState->provideInitialState( - 'mandatory2FAState', - $this->mandatoryTwoFactor->getState() - ); - - $parameters = [ - // Encryption API - 'encryptionEnabled' => $this->manager->isEnabled(), - 'encryptionReady' => $this->manager->isReady(), - 'externalBackendsEnabled' => count($this->userManager->getBackends()) > 1, - // Modules - 'encryptionModules' => $encryptionModuleList, - ]; + $this->initialState->provideInitialState('mandatory2FAState', $this->mandatoryTwoFactor->getState()); + $this->initialState->provideInitialState('two-factor-admin-doc', $this->urlGenerator->linkToDocs('admin-2fa')); + $this->initialState->provideInitialState('encryption-enabled', $this->manager->isEnabled()); + $this->initialState->provideInitialState('encryption-ready', $this->manager->isReady()); + $this->initialState->provideInitialState('external-backends-enabled', count($this->userManager->getBackends()) > 1); + $this->initialState->provideInitialState('encryption-modules', $encryptionModuleList); + $this->initialState->provideInitialState('encryption-admin-doc', $this->urlGenerator->linkToDocs('admin-encryption')); - return new TemplateResponse('settings', 'settings/admin/security', $parameters, ''); + return new TemplateResponse('settings', 'settings/admin/security', [], ''); } /** diff --git a/apps/settings/lib/Settings/Admin/Server.php b/apps/settings/lib/Settings/Admin/Server.php index 0fe98f21c8f..0d8ef00a1fd 100644 --- a/apps/settings/lib/Settings/Admin/Server.php +++ b/apps/settings/lib/Settings/Admin/Server.php @@ -33,28 +33,25 @@ use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; use OCP\IDBConnection; use OCP\IL10N; +use OCP\IURLGenerator; use OCP\Settings\IDelegatedSettings; class Server implements IDelegatedSettings { use TProfileHelper; - /** @var IDBConnection */ - private $connection; - /** @var IInitialState */ - private $initialStateService; - /** @var ProfileManager */ - private $profileManager; - /** @var ITimeFactory */ - private $timeFactory; - /** @var IConfig */ - private $config; - /** @var IL10N $l */ - private $l; + private IDBConnection $connection; + private IInitialState $initialStateService; + private ProfileManager $profileManager; + private ITimeFactory $timeFactory; + private IConfig $config; + private IL10N $l; + private IURLGenerator $urlGenerator; public function __construct(IDBConnection $connection, IInitialState $initialStateService, ProfileManager $profileManager, ITimeFactory $timeFactory, + IURLGenerator $urlGenerator, IConfig $config, IL10N $l) { $this->connection = $connection; @@ -63,27 +60,29 @@ class Server implements IDelegatedSettings { $this->timeFactory = $timeFactory; $this->config = $config; $this->l = $l; + $this->urlGenerator = $urlGenerator; } /** * @return TemplateResponse */ public function getForm() { - $parameters = [ - // Background jobs - 'backgroundjobs_mode' => $this->config->getAppValue('core', 'backgroundjobs_mode', 'ajax'), - 'lastcron' => $this->config->getAppValue('core', 'lastcron', false), - 'cronMaxAge' => $this->cronMaxAge(), - 'cronErrors' => $this->config->getAppValue('core', 'cronErrors'), - 'cli_based_cron_possible' => function_exists('posix_getpwuid'), - 'cli_based_cron_user' => function_exists('posix_getpwuid') ? posix_getpwuid(fileowner(\OC::$configDir . 'config.php'))['name'] : '', - 'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), - ]; + // Background jobs + $this->initialStateService->provideInitialState('backgroundJobsMode', $this->config->getAppValue('core', 'backgroundjobs_mode', 'ajax')); + $this->initialStateService->provideInitialState('lastCron', (int)$this->config->getAppValue('core', 'lastcron', '0')); + $this->initialStateService->provideInitialState('cronMaxAge', $this->cronMaxAge()); + $this->initialStateService->provideInitialState('cronErrors', $this->config->getAppValue('core', 'cronErrors')); + $this->initialStateService->provideInitialState('cliBasedCronPossible', function_exists('posix_getpwuid')); + $this->initialStateService->provideInitialState('cliBasedCronUser', function_exists('posix_getpwuid') ? posix_getpwuid(fileowner(\OC::$configDir . 'config.php'))['name'] : ''); + $this->initialStateService->provideInitialState('backgroundJobsDocUrl', $this->urlGenerator->linkToDocs('admin-background-jobs')); + // Profile page $this->initialStateService->provideInitialState('profileEnabledGlobally', $this->profileManager->isProfileEnabled()); $this->initialStateService->provideInitialState('profileEnabledByDefault', $this->isProfileEnabledByDefault($this->config)); - return new TemplateResponse('settings', 'settings/admin/server', $parameters, ''); + return new TemplateResponse('settings', 'settings/admin/server', [ + 'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), + ], ''); } protected function cronMaxAge(): int { diff --git a/apps/settings/lib/Settings/Admin/Sharing.php b/apps/settings/lib/Settings/Admin/Sharing.php index ffe1e5acd45..d3c6839b8f7 100644 --- a/apps/settings/lib/Settings/Admin/Sharing.php +++ b/apps/settings/lib/Settings/Admin/Sharing.php @@ -91,7 +91,7 @@ class Sharing implements IDelegatedSettings { 'restrictUserEnumerationFullMatch' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes'), 'restrictUserEnumerationFullMatchUserId' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_userid', 'yes'), 'restrictUserEnumerationFullMatchEmail' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes'), - 'restrictUserEnumerationFullMatchIgnoreSecondDisplayName' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_display_name', 'no'), + 'restrictUserEnumerationFullMatchIgnoreSecondDN' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no'), 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(false), 'passwordExcludedGroups' => $excludedPasswordGroupsList, 'passwordExcludedGroupsFeatureEnabled' => $this->config->getSystemValueBool('sharing.allow_disabled_password_enforcement_groups', false), diff --git a/apps/settings/lib/Settings/Personal/PersonalInfo.php b/apps/settings/lib/Settings/Personal/PersonalInfo.php index 4bac8e67fb7..104989d2c61 100644 --- a/apps/settings/lib/Settings/Personal/PersonalInfo.php +++ b/apps/settings/lib/Settings/Personal/PersonalInfo.php @@ -135,7 +135,6 @@ class PersonalInfo implements ISettings { $totalSpace = \OC_Helper::humanFileSize($storageInfo['total']); } - $languageParameters = $this->getLanguageMap($user); $localeParameters = $this->getLocales($user); $messageParameters = $this->getMessageParameters($account); @@ -144,45 +143,33 @@ class PersonalInfo implements ISettings { 'usage' => \OC_Helper::humanFileSize($storageInfo['used']), 'usage_relative' => round($storageInfo['relative']), 'quota' => $storageInfo['quota'], - 'avatarChangeSupported' => $user->canChangeAvatar(), 'federationEnabled' => $federationEnabled, 'lookupServerUploadEnabled' => $lookupServerUploadEnabled, - 'avatarScope' => $account->getProperty(IAccountManager::PROPERTY_AVATAR)->getScope(), - 'displayNameChangeSupported' => $user->canChangeDisplayName(), - 'displayName' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getValue(), - 'displayNameScope' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getScope(), - 'email' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(), - 'emailScope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(), - 'emailVerification' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getVerified(), - 'phone' => $account->getProperty(IAccountManager::PROPERTY_PHONE)->getValue(), - 'phoneScope' => $account->getProperty(IAccountManager::PROPERTY_PHONE)->getScope(), - 'address' => $account->getProperty(IAccountManager::PROPERTY_ADDRESS)->getValue(), - 'addressScope' => $account->getProperty(IAccountManager::PROPERTY_ADDRESS)->getScope(), - 'website' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getValue(), - 'websiteScope' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getScope(), - 'websiteVerification' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getVerified(), - 'twitter' => $account->getProperty(IAccountManager::PROPERTY_TWITTER)->getValue(), - 'twitterScope' => $account->getProperty(IAccountManager::PROPERTY_TWITTER)->getScope(), - 'twitterVerification' => $account->getProperty(IAccountManager::PROPERTY_TWITTER)->getVerified(), 'groups' => $this->getGroups($user), 'isFairUseOfFreePushService' => $this->isFairUseOfFreePushService(), 'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), - ] + $messageParameters + $languageParameters + $localeParameters; + ] + $messageParameters + $localeParameters; $personalInfoParameters = [ 'userId' => $uid, - 'displayNameMap' => $this->getDisplayNameMap($account), + 'avatar' => $this->getProperty($account, IAccountManager::PROPERTY_AVATAR), + 'displayName' => $this->getProperty($account, IAccountManager::PROPERTY_DISPLAYNAME), 'emailMap' => $this->getEmailMap($account), + 'phone' => $this->getProperty($account, IAccountManager::PROPERTY_PHONE), + 'location' => $this->getProperty($account, IAccountManager::PROPERTY_ADDRESS), + 'website' => $this->getProperty($account, IAccountManager::PROPERTY_WEBSITE), + 'twitter' => $this->getProperty($account, IAccountManager::PROPERTY_TWITTER), 'languageMap' => $this->getLanguageMap($user), 'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), 'profileEnabled' => $this->profileManager->isProfileEnabled($user), - 'organisationMap' => $this->getOrganisationMap($account), - 'roleMap' => $this->getRoleMap($account), - 'headlineMap' => $this->getHeadlineMap($account), - 'biographyMap' => $this->getBiographyMap($account), + 'organisation' => $this->getProperty($account, IAccountManager::PROPERTY_ORGANISATION), + 'role' => $this->getProperty($account, IAccountManager::PROPERTY_ROLE), + 'headline' => $this->getProperty($account, IAccountManager::PROPERTY_HEADLINE), + 'biography' => $this->getProperty($account, IAccountManager::PROPERTY_BIOGRAPHY), ]; $accountParameters = [ + 'avatarChangeSupported' => $user->canChangeAvatar(), 'displayNameChangeSupported' => $user->canChangeDisplayName(), 'lookupServerUploadEnabled' => $lookupServerUploadEnabled, ]; @@ -208,75 +195,18 @@ class PersonalInfo implements ISettings { } /** - * returns the primary biography in an - * associative array - */ - private function getBiographyMap(IAccount $account): array { - $primaryBiography = [ - 'value' => $account->getProperty(IAccountManager::PROPERTY_BIOGRAPHY)->getValue(), - 'scope' => $account->getProperty(IAccountManager::PROPERTY_BIOGRAPHY)->getScope(), - 'verified' => $account->getProperty(IAccountManager::PROPERTY_BIOGRAPHY)->getVerified(), - ]; - - $biographyMap = [ - 'primaryBiography' => $primaryBiography, - ]; - - return $biographyMap; - } - - /** - * returns the primary organisation in an - * associative array - */ - private function getOrganisationMap(IAccount $account): array { - $primaryOrganisation = [ - 'value' => $account->getProperty(IAccountManager::PROPERTY_ORGANISATION)->getValue(), - 'scope' => $account->getProperty(IAccountManager::PROPERTY_ORGANISATION)->getScope(), - 'verified' => $account->getProperty(IAccountManager::PROPERTY_ORGANISATION)->getVerified(), - ]; - - $organisationMap = [ - 'primaryOrganisation' => $primaryOrganisation, - ]; - - return $organisationMap; - } - - /** - * returns the primary headline in an + * returns the property data in an * associative array */ - private function getHeadlineMap(IAccount $account): array { - $primaryHeadline = [ - 'value' => $account->getProperty(IAccountManager::PROPERTY_HEADLINE)->getValue(), - 'scope' => $account->getProperty(IAccountManager::PROPERTY_HEADLINE)->getScope(), - 'verified' => $account->getProperty(IAccountManager::PROPERTY_HEADLINE)->getVerified(), + private function getProperty(IAccount $account, string $property): array { + $property = [ + 'name' => $account->getProperty($property)->getName(), + 'value' => $account->getProperty($property)->getValue(), + 'scope' => $account->getProperty($property)->getScope(), + 'verified' => $account->getProperty($property)->getVerified(), ]; - $headlineMap = [ - 'primaryHeadline' => $primaryHeadline, - ]; - - return $headlineMap; - } - - /** - * returns the primary role in an - * associative array - */ - private function getRoleMap(IAccount $account): array { - $primaryRole = [ - 'value' => $account->getProperty(IAccountManager::PROPERTY_ROLE)->getValue(), - 'scope' => $account->getProperty(IAccountManager::PROPERTY_ROLE)->getScope(), - 'verified' => $account->getProperty(IAccountManager::PROPERTY_ROLE)->getVerified(), - ]; - - $roleMap = [ - 'primaryRole' => $primaryRole, - ]; - - return $roleMap; + return $property; } /** @@ -315,31 +245,12 @@ class PersonalInfo implements ISettings { } /** - * returns the primary display name in an - * associative array - * - * NOTE may be extended to provide additional display names (i.e. aliases) in the future - */ - private function getDisplayNameMap(IAccount $account): array { - $primaryDisplayName = [ - 'value' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getValue(), - 'scope' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getScope(), - 'verified' => $account->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getVerified(), - ]; - - $displayNameMap = [ - 'primaryDisplayName' => $primaryDisplayName, - ]; - - return $displayNameMap; - } - - /** * returns the primary email and additional emails in an * associative array */ private function getEmailMap(IAccount $account): array { $systemEmail = [ + 'name' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getName(), 'value' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(), 'scope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(), 'verified' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getVerified(), @@ -348,6 +259,7 @@ class PersonalInfo implements ISettings { $additionalEmails = array_map( function (IAccountProperty $property) { return [ + 'name' => $property->getName(), 'value' => $property->getValue(), 'scope' => $property->getScope(), 'verified' => $property->getVerified(), diff --git a/apps/settings/lib/SetupChecks/SupportedDatabase.php b/apps/settings/lib/SetupChecks/SupportedDatabase.php index 089fb69bbc9..302797485d3 100644 --- a/apps/settings/lib/SetupChecks/SupportedDatabase.php +++ b/apps/settings/lib/SetupChecks/SupportedDatabase.php @@ -70,12 +70,12 @@ class SupportedDatabase { if (strpos($version, 'mariadb') !== false) { if (version_compare($version, '10.2', '<')) { - $this->description = $this->l10n->t('MariaDB version "%s" is used. Nextcloud 21 will no longer support this version and requires MariaDB 10.2 or higher.', $row['Value']); + $this->description = $this->l10n->t('MariaDB version "%s" is used. Nextcloud 21 and higher do not support this version and require MariaDB 10.2 or higher.', $row['Value']); return; } } else { if (version_compare($version, '8', '<')) { - $this->description = $this->l10n->t('MySQL version "%s" is used. Nextcloud 21 will no longer support this version and requires MySQL 8.0 or MariaDB 10.2 or higher.', $row['Value']); + $this->description = $this->l10n->t('MySQL version "%s" is used. Nextcloud 21 and higher do not support this version and require MySQL 8.0 or MariaDB 10.2 or higher.', $row['Value']); return; } } @@ -88,7 +88,7 @@ class SupportedDatabase { $result->execute(); $row = $result->fetch(); if (version_compare($row['server_version'], '9.6', '<')) { - $this->description = $this->l10n->t('PostgreSQL version "%s" is used. Nextcloud 21 will no longer support this version and requires PostgreSQL 9.6 or higher.', $row['server_version']); + $this->description = $this->l10n->t('PostgreSQL version "%s" is used. Nextcloud 21 and higher do not support this version and require PostgreSQL 9.6 or higher.', $row['server_version']); return; } break; diff --git a/apps/settings/lib/UserMigration/AccountMigrator.php b/apps/settings/lib/UserMigration/AccountMigrator.php index 7b60a101cee..e8c70624224 100644 --- a/apps/settings/lib/UserMigration/AccountMigrator.php +++ b/apps/settings/lib/UserMigration/AccountMigrator.php @@ -28,7 +28,9 @@ namespace OCA\Settings\UserMigration; use InvalidArgumentException; use OC\Accounts\TAccountsHelper; +use OC\Core\Db\ProfileConfigMapper; use OC\NotSquareException; +use OC\Profile\ProfileManager; use OCA\Settings\AppInfo\Application; use OCP\Accounts\IAccountManager; use OCP\IAvatarManager; @@ -37,11 +39,12 @@ use OCP\IUser; use OCP\UserMigration\IExportDestination; use OCP\UserMigration\IImportSource; use OCP\UserMigration\IMigrator; +use OCP\UserMigration\ISizeEstimationMigrator; use OCP\UserMigration\TMigratorBasicVersionHandling; use Symfony\Component\Console\Output\OutputInterface; use Throwable; -class AccountMigrator implements IMigrator { +class AccountMigrator implements IMigrator, ISizeEstimationMigrator { use TMigratorBasicVersionHandling; use TAccountsHelper; @@ -50,6 +53,10 @@ class AccountMigrator implements IMigrator { private IAvatarManager $avatarManager; + private ProfileManager $profileManager; + + private ProfileConfigMapper $configMapper; + private IL10N $l10n; private const PATH_ROOT = Application::APP_ID . '/'; @@ -58,19 +65,44 @@ class AccountMigrator implements IMigrator { private const AVATAR_BASENAME = 'avatar'; + private const PATH_CONFIG_FILE = AccountMigrator::PATH_ROOT . 'config.json'; + public function __construct( IAccountManager $accountManager, IAvatarManager $avatarManager, + ProfileManager $profileManager, + ProfileConfigMapper $configMapper, IL10N $l10n ) { $this->accountManager = $accountManager; $this->avatarManager = $avatarManager; + $this->profileManager = $profileManager; + $this->configMapper = $configMapper; $this->l10n = $l10n; } /** * {@inheritDoc} */ + public function getEstimatedExportSize(IUser $user): int { + $size = 100; // 100KiB for account JSON + + try { + $avatar = $this->avatarManager->getAvatar($user->getUID()); + if ($avatar->isCustomAvatar()) { + $avatarFile = $avatar->getFile(-1); + $size += $avatarFile->getSize() / 1024; + } + } catch (Throwable $e) { + // Skip avatar in size estimate on failure + } + + return (int)ceil($size); + } + + /** + * {@inheritDoc} + */ public function export(IUser $user, IExportDestination $exportDestination, OutputInterface $output): void { $output->writeln('Exporting account information in ' . AccountMigrator::PATH_ACCOUNT_FILE . '…'); @@ -93,6 +125,14 @@ class AccountMigrator implements IMigrator { } catch (Throwable $e) { throw new AccountMigratorException('Could not export avatar', 0, $e); } + + try { + $output->writeln('Exporting profile config in ' . AccountMigrator::PATH_CONFIG_FILE . '…'); + $config = $this->profileManager->getProfileConfig($user, $user); + $exportDestination->addFileContents(AccountMigrator::PATH_CONFIG_FILE, json_encode($config)); + } catch (Throwable $e) { + throw new AccountMigratorException('Could not export profile config', 0, $e); + } } /** @@ -133,7 +173,7 @@ class AccountMigrator implements IMigrator { $output->writeln('Importing avatar from ' . $importPath . '…'); $stream = $importSource->getFileAsStream($importPath); - $image = new \OC_Image(); + $image = new \OCP\Image(); $image->loadFromFileHandle($stream); try { @@ -145,6 +185,19 @@ class AccountMigrator implements IMigrator { throw new AccountMigratorException('Failed to import avatar', 0, $e); } } + + try { + $output->writeln('Importing profile config from ' . AccountMigrator::PATH_CONFIG_FILE . '…'); + /** @var array $configData */ + $configData = json_decode($importSource->getFileContents(AccountMigrator::PATH_CONFIG_FILE), true, 512, JSON_THROW_ON_ERROR); + // Ensure that a profile config entry exists in the database + $this->profileManager->getProfileConfig($user, $user); + $config = $this->configMapper->get($user->getUID()); + $config->setConfigArray($configData); + $this->configMapper->update($config); + } catch (Throwable $e) { + throw new AccountMigratorException('Failed to import profile config'); + } } /** |