diff --git a/appinfo/info.xml b/appinfo/info.xml index 0799dd3d..90febffd 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -8,7 +8,7 @@ OpenID Connect user backend Use an OpenID Connect backend to login to your Nextcloud Allows flexible configuration of an OIDC server as Nextcloud login user backend. - 8.1.0 + 8.1.1 agpl Roeland Jago Douma Julius Härtl diff --git a/lib/Controller/LoginController.php b/lib/Controller/LoginController.php index da786660..8bd798a8 100644 --- a/lib/Controller/LoginController.php +++ b/lib/Controller/LoginController.php @@ -601,7 +601,7 @@ public function code(string $state = '', string $code = '', string $scope = '', $this->eventDispatcher->dispatchTyped(new UserLoggedInEvent($user, $user->getUID(), null, false)); } - $storeLoginTokenEnabled = $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0') === '1'; + $storeLoginTokenEnabled = $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0', lazy: true) === '1'; if ($storeLoginTokenEnabled) { // store all token information for potential token exchange requests $tokenData = array_merge( diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index d4d6b42d..004edc04 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -180,7 +180,7 @@ public function setID4ME(bool $enabled): JSONResponse { public function setAdminConfig(array $values): JSONResponse { foreach ($values as $key => $value) { if ($key === 'store_login_token' && is_bool($value)) { - $this->appConfig->setValueString(Application::APP_ID, 'store_login_token', $value ? '1' : '0'); + $this->appConfig->setValueString(Application::APP_ID, 'store_login_token', $value ? '1' : '0', lazy: true); } } return new JSONResponse([]); diff --git a/lib/Listener/ExternalTokenRequestedListener.php b/lib/Listener/ExternalTokenRequestedListener.php index 65e3cbc7..277a00a0 100644 --- a/lib/Listener/ExternalTokenRequestedListener.php +++ b/lib/Listener/ExternalTokenRequestedListener.php @@ -42,7 +42,7 @@ public function handle(Event $event): void { $this->logger->debug('[ExternalTokenRequestedListener] received request'); - $storeLoginTokenEnabled = $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0') === '1'; + $storeLoginTokenEnabled = $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0', lazy: true) === '1'; if (!$storeLoginTokenEnabled) { throw new GetExternalTokenFailedException('Failed to get external token, login token is not stored', 0); } diff --git a/lib/Migration/Version080101Date20251201121749.php b/lib/Migration/Version080101Date20251201121749.php new file mode 100644 index 00000000..aff765b9 --- /dev/null +++ b/lib/Migration/Version080101Date20251201121749.php @@ -0,0 +1,69 @@ +appConfig->hasKey(Application::APP_ID, $key)) { + $value = $this->appConfig->getValueString(Application::APP_ID, $key); + $this->appConfig->setValueString(Application::APP_ID, $key, $value, lazy: true); + } + } catch (\Exception) { + } + } + + // make all provider settings lazy + $providers = $this->providerMapper->getProviders(); + $supportedSettingKeys = $this->providerService->getSupportedSettings(); + $supportedSettingKeys[] = ProviderService::SETTING_JWKS_CACHE; + $supportedSettingKeys[] = ProviderService::SETTING_JWKS_CACHE_TIMESTAMP; + foreach ($supportedSettingKeys as $key) { + foreach ($providers as $provider) { + $realKey = $this->providerService->getSettingsKey($provider->getId(), $key); + if ($this->appConfig->hasKey(Application::APP_ID, $realKey)) { + try { + $value = $this->appConfig->getValueString(Application::APP_ID, $realKey); + $this->appConfig->setValueString(Application::APP_ID, $realKey, $value, lazy: true); + } catch (\Exception) { + } + } + } + } + } +} diff --git a/lib/Service/ID4MeService.php b/lib/Service/ID4MeService.php index 52ad45a8..4f5ac76b 100644 --- a/lib/Service/ID4MeService.php +++ b/lib/Service/ID4MeService.php @@ -19,10 +19,10 @@ public function __construct( } public function setID4ME(bool $enabled): void { - $this->appConfig->setValueString(Application::APP_ID, 'id4me_enabled', $enabled ? '1' : '0'); + $this->appConfig->setValueString(Application::APP_ID, 'id4me_enabled', $enabled ? '1' : '0', lazy: true); } public function getID4ME(): bool { - return $this->appConfig->getValueString(Application::APP_ID, 'id4me_enabled', '0') === '1'; + return $this->appConfig->getValueString(Application::APP_ID, 'id4me_enabled', '0', lazy: true) === '1'; } } diff --git a/lib/Service/ProviderService.php b/lib/Service/ProviderService.php index 8c67d88d..bfda134b 100644 --- a/lib/Service/ProviderService.php +++ b/lib/Service/ProviderService.php @@ -125,22 +125,22 @@ public function deleteSettings(int $providerId): void { } public function setSetting(int $providerId, string $key, string $value): void { - $this->appConfig->setValueString(Application::APP_ID, $this->getSettingsKey($providerId, $key), $value); + $this->appConfig->setValueString(Application::APP_ID, $this->getSettingsKey($providerId, $key), $value, lazy: true); } public function getSetting(int $providerId, string $key, string $default = ''): string { - $value = $this->appConfig->getValueString(Application::APP_ID, $this->getSettingsKey($providerId, $key), ''); + $value = $this->appConfig->getValueString(Application::APP_ID, $this->getSettingsKey($providerId, $key), '', lazy: true); if ($value === '') { return $default; } return $value; } - private function getSettingsKey(int $providerId, string $key): string { + public function getSettingsKey(int $providerId, string $key): string { return 'provider-' . strval($providerId) . '-' . $key; } - private function getSupportedSettings(): array { + public function getSupportedSettings(): array { return [ self::SETTING_MAPPING_DISPLAYNAME, self::SETTING_MAPPING_EMAIL, diff --git a/lib/Service/SettingsService.php b/lib/Service/SettingsService.php index dc06ba82..ffd75d34 100644 --- a/lib/Service/SettingsService.php +++ b/lib/Service/SettingsService.php @@ -25,7 +25,7 @@ public function __construct( public function getAllowMultipleUserBackEnds(): bool { try { - return $this->appConfig->getValueString(Application::APP_ID, 'allow_multiple_user_backends', '1') === '1'; + return $this->appConfig->getValueString(Application::APP_ID, 'allow_multiple_user_backends', '1', lazy: true) === '1'; } catch (AppConfigTypeConflictException $e) { $this->logger->warning('Incorrect app config type when getting "allow_multiple_user_backends"', ['exception' => $e]); return true; @@ -34,11 +34,11 @@ public function getAllowMultipleUserBackEnds(): bool { public function setAllowMultipleUserBackEnds(bool $value): void { try { - $this->appConfig->setValueString(Application::APP_ID, 'allow_multiple_user_backends', $value ? '1' : '0'); + $this->appConfig->setValueString(Application::APP_ID, 'allow_multiple_user_backends', $value ? '1' : '0', lazy: true); } catch (AppConfigTypeConflictException $e) { $this->logger->warning('Incorrect app config type when setting "allow_multiple_user_backends"', ['exception' => $e]); $this->appConfig->deleteKey(Application::APP_ID, 'allow_multiple_user_backends'); - $this->appConfig->setValueString(Application::APP_ID, 'allow_multiple_user_backends', $value ? '1' : '0'); + $this->appConfig->setValueString(Application::APP_ID, 'allow_multiple_user_backends', $value ? '1' : '0', lazy: true); } } } diff --git a/lib/Service/TokenService.php b/lib/Service/TokenService.php index 1cab6845..e2f387cb 100644 --- a/lib/Service/TokenService.php +++ b/lib/Service/TokenService.php @@ -116,7 +116,7 @@ public function getToken(bool $refreshIfExpired = true): ?Token { * @throws PreConditionNotMetException */ public function checkLoginToken(): void { - $storeLoginTokenEnabled = $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0') === '1'; + $storeLoginTokenEnabled = $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0', lazy: true) === '1'; if (!$storeLoginTokenEnabled) { return; } @@ -255,7 +255,7 @@ public function decodeIdToken(Token $token): array { * @throws \JsonException */ public function getExchangedToken(string $targetAudience, array $extraScopes = []): Token { - $storeLoginTokenEnabled = $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0') === '1'; + $storeLoginTokenEnabled = $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0', lazy: true) === '1'; if (!$storeLoginTokenEnabled) { throw new TokenExchangeFailedException( 'Failed to exchange token, storing the login token is disabled. It can be enabled in config.php', diff --git a/lib/Settings/AdminSettings.php b/lib/Settings/AdminSettings.php index 99607439..332caa6e 100644 --- a/lib/Settings/AdminSettings.php +++ b/lib/Settings/AdminSettings.php @@ -37,7 +37,7 @@ public function getForm() { ); $this->initialStateService->provideInitialState( 'storeLoginTokenState', - $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0') === '1' + $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0', lazy: true) === '1' ); $this->initialStateService->provideInitialState( 'providers', diff --git a/tests/unit/Service/ProviderServiceTest.php b/tests/unit/Service/ProviderServiceTest.php index ab739847..7205a7bc 100644 --- a/tests/unit/Service/ProviderServiceTest.php +++ b/tests/unit/Service/ProviderServiceTest.php @@ -189,41 +189,41 @@ public function testSetSettings() { $this->appConfig->expects(self::any()) ->method('getValueString') ->willReturnMap([ - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_DISPLAYNAME, '', 'dn'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_EMAIL, '', 'mail'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_QUOTA, '', '1g'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_UID, '', 'uid'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_GROUPS, '', 'groups'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_LANGUAGE, '', 'language'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_LOCALE, '', 'locale'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_ADDRESS, '', 'address'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_STREETADDRESS, '', 'street_address'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_POSTALCODE, '', 'postal_code'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_LOCALITY, '', 'locality'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_REGION, '', 'region'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_COUNTRY, '', 'country'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_WEBSITE, '', 'website'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_AVATAR, '', 'avatar'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_TWITTER, '', 'twitter'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_FEDIVERSE, '', 'fediverse'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_ORGANISATION, '', 'organisation'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_ROLE, '', 'role'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_HEADLINE, '', 'headline'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_BIOGRAPHY, '', 'biography'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_PHONE, '', 'phone'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_GENDER, '', 'gender'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_PRONOUNS, '', 'pronouns'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_BIRTHDATE, '', 'birthdate'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_UNIQUE_UID, '', '1'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_CHECK_BEARER, '', '0'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_BEARER_PROVISIONING, '', '0'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_SEND_ID_TOKEN_HINT, '', '1'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_EXTRA_CLAIMS, '', 'claim1 claim2'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_PROVIDER_BASED_ID, '', '0'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_GROUP_PROVISIONING, '', '1'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_GROUP_WHITELIST_REGEX, '', ''], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_RESTRICT_LOGIN_TO_GROUPS, '', '0'], - [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING, '', '0'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_DISPLAYNAME, '', true, 'dn'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_EMAIL, '', true, 'mail'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_QUOTA, '', true, '1g'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_UID, '', true, 'uid'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_GROUPS, '', true, 'groups'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_LANGUAGE, '', true, 'language'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_LOCALE, '', true, 'locale'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_ADDRESS, '', true, 'address'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_STREETADDRESS, '', true, 'street_address'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_POSTALCODE, '', true, 'postal_code'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_LOCALITY, '', true, 'locality'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_REGION, '', true, 'region'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_COUNTRY, '', true, 'country'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_WEBSITE, '', true, 'website'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_AVATAR, '', true, 'avatar'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_TWITTER, '', true, 'twitter'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_FEDIVERSE, '', true, 'fediverse'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_ORGANISATION, '', true, 'organisation'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_ROLE, '', true, 'role'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_HEADLINE, '', true, 'headline'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_BIOGRAPHY, '', true, 'biography'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_PHONE, '', true, 'phone'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_GENDER, '', true, 'gender'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_PRONOUNS, '', true, 'pronouns'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_MAPPING_BIRTHDATE, '', true, 'birthdate'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_UNIQUE_UID, '', true, '1'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_CHECK_BEARER, '', true, '0'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_BEARER_PROVISIONING, '', true, '0'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_SEND_ID_TOKEN_HINT, '', true, '1'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_EXTRA_CLAIMS, '', true, 'claim1 claim2'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_PROVIDER_BASED_ID, '', true, '0'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_GROUP_PROVISIONING, '', true, '1'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_GROUP_WHITELIST_REGEX, '', true, ''], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_RESTRICT_LOGIN_TO_GROUPS, '', true, '0'], + [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING, '', true, '0'], ]); Assert::assertEquals(