diff options
Diffstat (limited to 'apps/settings/lib')
6 files changed, 63 insertions, 15 deletions
diff --git a/apps/settings/lib/Controller/AISettingsController.php b/apps/settings/lib/Controller/AISettingsController.php index a3b0a874987..114cbf61514 100644 --- a/apps/settings/lib/Controller/AISettingsController.php +++ b/apps/settings/lib/Controller/AISettingsController.php @@ -12,20 +12,15 @@ use OCA\Settings\Settings\Admin\ArtificialIntelligence; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting; use OCP\AppFramework\Http\DataResponse; -use OCP\IConfig; +use OCP\IAppConfig; use OCP\IRequest; class AISettingsController extends Controller { - /** - * @param string $appName - * @param IRequest $request - * @param IConfig $config - */ public function __construct( $appName, IRequest $request, - private IConfig $config, + private IAppConfig $appConfig, ) { parent::__construct($appName, $request); } @@ -43,7 +38,7 @@ class AISettingsController extends Controller { if (!isset($settings[$key])) { continue; } - $this->config->setAppValue('core', $key, json_encode($settings[$key])); + $this->appConfig->setValueString('core', $key, json_encode($settings[$key]), lazy: in_array($key, \OC\TaskProcessing\Manager::LAZY_CONFIG_KEYS, true)); } return new DataResponse(); diff --git a/apps/settings/lib/Controller/AppSettingsController.php b/apps/settings/lib/Controller/AppSettingsController.php index 3feb9c0326c..a85ee8cc20a 100644 --- a/apps/settings/lib/Controller/AppSettingsController.php +++ b/apps/settings/lib/Controller/AppSettingsController.php @@ -23,7 +23,6 @@ use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired; -use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\ContentSecurityPolicy; use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Http\JSONResponse; @@ -45,7 +44,9 @@ use OCP\IL10N; use OCP\INavigationManager; use OCP\IRequest; use OCP\IURLGenerator; +use OCP\IUserSession; use OCP\L10N\IFactory; +use OCP\Security\RateLimiting\ILimiter; use OCP\Server; use OCP\Util; use Psr\Log\LoggerInterface; @@ -129,9 +130,8 @@ class AppSettingsController extends Controller { * @param string $image * @throws \Exception */ - #[PublicPage] #[NoCSRFRequired] - public function getAppDiscoverMedia(string $fileName): Response { + public function getAppDiscoverMedia(string $fileName, ILimiter $limiter, IUserSession $session): Response { $getEtag = $this->discoverFetcher->getETag() ?? date('Y-m'); $etag = trim($getEtag, '"'); @@ -161,6 +161,26 @@ class AppSettingsController extends Controller { $file = reset($file); // If not found request from Web if ($file === false) { + $user = $session->getUser(); + // this route is not public thus we can assume a user is logged-in + assert($user !== null); + // Register a user request to throttle fetching external data + // this will prevent using the server for DoS of other systems. + $limiter->registerUserRequest( + 'settings-discover-media', + // allow up to 24 media requests per hour + // this should be a sane default when a completely new section is loaded + // keep in mind browsers request all files from a source-set + 24, + 60 * 60, + $user, + ); + + if (!$this->checkCanDownloadMedia($fileName)) { + $this->logger->warning('Tried to load media files for app discover section from untrusted source'); + return new NotFoundResponse(Http::STATUS_BAD_REQUEST); + } + try { $client = $this->clientService->newClient(); $fileResponse = $client->get($fileName); @@ -182,6 +202,31 @@ class AppSettingsController extends Controller { return $response; } + private function checkCanDownloadMedia(string $filename): bool { + $urlInfo = parse_url($filename); + if (!isset($urlInfo['host']) || !isset($urlInfo['path'])) { + return false; + } + + // Always allowed hosts + if ($urlInfo['host'] === 'nextcloud.com') { + return true; + } + + // Hosts that need further verification + // Github is only allowed if from our organization + $ALLOWED_HOSTS = ['github.com', 'raw.githubusercontent.com']; + if (!in_array($urlInfo['host'], $ALLOWED_HOSTS)) { + return false; + } + + if (str_starts_with($urlInfo['path'], '/nextcloud/') || str_starts_with($urlInfo['path'], '/nextcloud-gmbh/')) { + return true; + } + + return false; + } + /** * Remove orphaned folders from the image cache that do not match the current etag * @param ISimpleFolder $folder The folder to clear diff --git a/apps/settings/lib/Controller/UsersController.php b/apps/settings/lib/Controller/UsersController.php index 6cd596d6cc8..8efd3eeb8ca 100644 --- a/apps/settings/lib/Controller/UsersController.php +++ b/apps/settings/lib/Controller/UsersController.php @@ -319,6 +319,8 @@ class UsersController extends Controller { * @param string|null $addressScope * @param string|null $twitter * @param string|null $twitterScope + * @param string|null $bluesky + * @param string|null $blueskyScope * @param string|null $fediverse * @param string|null $fediverseScope * @param string|null $birthdate @@ -342,6 +344,8 @@ class UsersController extends Controller { ?string $addressScope = null, ?string $twitter = null, ?string $twitterScope = null, + ?string $bluesky = null, + ?string $blueskyScope = null, ?string $fediverse = null, ?string $fediverseScope = null, ?string $birthdate = null, @@ -386,6 +390,7 @@ class UsersController extends Controller { IAccountManager::PROPERTY_ADDRESS => ['value' => $address, 'scope' => $addressScope], IAccountManager::PROPERTY_PHONE => ['value' => $phone, 'scope' => $phoneScope], IAccountManager::PROPERTY_TWITTER => ['value' => $twitter, 'scope' => $twitterScope], + IAccountManager::PROPERTY_BLUESKY => ['value' => $bluesky, 'scope' => $blueskyScope], IAccountManager::PROPERTY_FEDIVERSE => ['value' => $fediverse, 'scope' => $fediverseScope], IAccountManager::PROPERTY_BIRTHDATE => ['value' => $birthdate, 'scope' => $birthdateScope], IAccountManager::PROPERTY_PRONOUNS => ['value' => $pronouns, 'scope' => $pronounsScope], @@ -428,6 +433,8 @@ class UsersController extends Controller { 'addressScope' => $userAccount->getProperty(IAccountManager::PROPERTY_ADDRESS)->getScope(), 'twitter' => $userAccount->getProperty(IAccountManager::PROPERTY_TWITTER)->getValue(), 'twitterScope' => $userAccount->getProperty(IAccountManager::PROPERTY_TWITTER)->getScope(), + 'bluesky' => $userAccount->getProperty(IAccountManager::PROPERTY_BLUESKY)->getValue(), + 'blueskyScope' => $userAccount->getProperty(IAccountManager::PROPERTY_BLUESKY)->getScope(), 'fediverse' => $userAccount->getProperty(IAccountManager::PROPERTY_FEDIVERSE)->getValue(), 'fediverseScope' => $userAccount->getProperty(IAccountManager::PROPERTY_FEDIVERSE)->getScope(), 'birthdate' => $userAccount->getProperty(IAccountManager::PROPERTY_BIRTHDATE)->getValue(), diff --git a/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php b/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php index 78bec73382d..aaec0049b20 100644 --- a/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php +++ b/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php @@ -10,7 +10,7 @@ namespace OCA\Settings\Settings\Admin; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; -use OCP\IConfig; +use OCP\IAppConfig; use OCP\IL10N; use OCP\Settings\IDelegatedSettings; use OCP\SpeechToText\ISpeechToTextManager; @@ -28,7 +28,7 @@ use Psr\Log\LoggerInterface; class ArtificialIntelligence implements IDelegatedSettings { public function __construct( - private IConfig $config, + private IAppConfig $appConfig, private IL10N $l, private IInitialState $initialState, private ITranslationManager $translationManager, @@ -145,7 +145,7 @@ class ArtificialIntelligence implements IDelegatedSettings { ]; foreach ($settings as $key => $defaultValue) { $value = $defaultValue; - $json = $this->config->getAppValue('core', $key, ''); + $json = $this->appConfig->getValueString('core', $key, '', lazy: in_array($key, \OC\TaskProcessing\Manager::LAZY_CONFIG_KEYS, true)); if ($json !== '') { try { $value = json_decode($json, true, flags: JSON_THROW_ON_ERROR); diff --git a/apps/settings/lib/Settings/Personal/PersonalInfo.php b/apps/settings/lib/Settings/Personal/PersonalInfo.php index 84b379f2e87..9a12b18bb5e 100644 --- a/apps/settings/lib/Settings/Personal/PersonalInfo.php +++ b/apps/settings/lib/Settings/Personal/PersonalInfo.php @@ -98,6 +98,7 @@ class PersonalInfo implements ISettings { 'location' => $this->getProperty($account, IAccountManager::PROPERTY_ADDRESS), 'website' => $this->getProperty($account, IAccountManager::PROPERTY_WEBSITE), 'twitter' => $this->getProperty($account, IAccountManager::PROPERTY_TWITTER), + 'bluesky' => $this->getProperty($account, IAccountManager::PROPERTY_BLUESKY), 'fediverse' => $this->getProperty($account, IAccountManager::PROPERTY_FEDIVERSE), 'languageMap' => $this->getLanguageMap($user), 'localeMap' => $this->getLocaleMap($user), diff --git a/apps/settings/lib/SetupChecks/SupportedDatabase.php b/apps/settings/lib/SetupChecks/SupportedDatabase.php index 31b907a825e..d083958d16e 100644 --- a/apps/settings/lib/SetupChecks/SupportedDatabase.php +++ b/apps/settings/lib/SetupChecks/SupportedDatabase.php @@ -21,7 +21,7 @@ use OCP\SetupCheck\SetupResult; class SupportedDatabase implements ISetupCheck { private const MIN_MARIADB = '10.6'; - private const MAX_MARIADB = '11.4'; + private const MAX_MARIADB = '11.8'; private const MIN_MYSQL = '8.0'; private const MAX_MYSQL = '8.4'; private const MIN_POSTGRES = '13'; |