diff --git a/appinfo/info.xml b/appinfo/info.xml
index b67271e6..d5c3840d 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -4,7 +4,7 @@
Google integration
Import Google data into Nextcloud
- 4.2.0
+ 4.3.0
agpl
Julien Veyssier
Google
@@ -16,7 +16,7 @@
https://github.com/nextcloud/integration_google/issues
https://github.com/nextcloud/integration_google/raw/master/img/screenshot1.jpg
-
+
OCA\Google\Settings\Admin
diff --git a/lib/Controller/ConfigController.php b/lib/Controller/ConfigController.php
index b31f00df..a26ebf91 100644
--- a/lib/Controller/ConfigController.php
+++ b/lib/Controller/ConfigController.php
@@ -23,10 +23,11 @@
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Services\IInitialState;
+use OCP\Config\IUserConfig;
use OCP\Constants;
use OCP\Contacts\IManager as IContactManager;
-use OCP\IConfig;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IURLGenerator;
@@ -44,7 +45,8 @@ class ConfigController extends Controller {
public function __construct(
string $appName,
IRequest $request,
- private IConfig $config,
+ private IAppConfig $appConfig,
+ private IUserConfig $userConfig,
private IURLGenerator $urlGenerator,
private IL10N $l,
private IContactManager $contactsManager,
@@ -70,16 +72,16 @@ public function setConfig(array $values): DataResponse {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
foreach ($values as $key => $value) {
- $this->config->setUserValue($this->userId, Application::APP_ID, $key, $value);
+ $this->userConfig->setValueString($this->userId, Application::APP_ID, $key, $value, lazy: true);
}
$result = [];
if (isset($values['user_name']) && $values['user_name'] === '') {
- $this->config->deleteUserValue($this->userId, Application::APP_ID, 'user_id');
- $this->config->deleteUserValue($this->userId, Application::APP_ID, 'user_name');
- $this->config->deleteUserValue($this->userId, Application::APP_ID, 'refresh_token');
- $this->config->deleteUserValue($this->userId, Application::APP_ID, 'token_expires_at');
- $this->config->deleteUserValue($this->userId, Application::APP_ID, 'token');
+ $this->userConfig->deleteUserConfig($this->userId, Application::APP_ID, 'user_id');
+ $this->userConfig->deleteUserConfig($this->userId, Application::APP_ID, 'user_name');
+ $this->userConfig->deleteUserConfig($this->userId, Application::APP_ID, 'refresh_token');
+ $this->userConfig->deleteUserConfig($this->userId, Application::APP_ID, 'token_expires_at');
+ $this->userConfig->deleteUserConfig($this->userId, Application::APP_ID, 'token');
$result['user_name'] = '';
} else {
if (isset($values['drive_output_dir'])) {
@@ -106,10 +108,8 @@ public function setAdminConfig(array $values): DataResponse {
if ($key === 'client_secret' && $value === 'dummySecret') {
continue;
}
- if (in_array($key, ['client_secret', 'client_id'], true) && $value !== '') {
- $value = $this->crypto->encrypt($value);
- }
- $this->config->setAppValue(Application::APP_ID, $key, $value);
+ $sensitive = in_array($key, ['client_secret', 'client_id'], true);
+ $this->appConfig->setAppValueString($key, $value, lazy: true, sensitive: $sensitive);
}
return new DataResponse(1);
}
@@ -172,9 +172,9 @@ public function oauthRedirect(string $code = '', string $state = '', string $sco
);
}
- $configState = $this->config->getUserValue($this->userId, Application::APP_ID, 'oauth_state');
- $clientID = $this->secretService->getEncryptedAppValue('client_id');
- $clientSecret = $this->secretService->getEncryptedAppValue('client_secret');
+ $configState = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'oauth_state', lazy: true);
+ $clientID = $this->appConfig->getAppValueString('client_id', lazy: true);
+ $clientSecret = $this->appConfig->getAppValueString('client_secret', lazy: true);
// Store given scopes in space-separated string
$scopes = explode(' ', $scope);
@@ -186,13 +186,13 @@ public function oauthRedirect(string $code = '', string $state = '', string $sco
'can_access_calendar' => (in_array(self::CALENDAR_SCOPE, $scopes) && in_array(self::CALENDAR_EVENTS_SCOPE, $scopes)) ? 1 : 0,
];
- $this->config->setUserValue($this->userId, Application::APP_ID, 'user_scopes', json_encode($scopesArray));
+ $this->userConfig->setValueString($this->userId, Application::APP_ID, 'user_scopes', json_encode($scopesArray), lazy: true);
// anyway, reset state
- $this->config->setUserValue($this->userId, Application::APP_ID, 'oauth_state', '');
+ $this->userConfig->setValueString($this->userId, Application::APP_ID, 'oauth_state', '', lazy: true);
if ($clientID && $clientSecret && $configState !== '' && $configState === $state) {
- $redirect_uri = $this->config->getUserValue($this->userId, Application::APP_ID, 'redirect_uri');
+ $redirect_uri = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'redirect_uri', lazy: true);
/** @var array{access_token?:string, refresh_token?:string, expires_in?:string, error?:string} $result */
$result = $this->googleApiService->requestOAuthAccessToken([
'client_id' => $clientID,
@@ -207,12 +207,12 @@ public function oauthRedirect(string $code = '', string $state = '', string $sco
if (isset($result['expires_in'])) {
$nowTs = (new DateTime())->getTimestamp();
$expiresAt = $nowTs + (int)$result['expires_in'];
- $this->config->setUserValue($this->userId, Application::APP_ID, 'token_expires_at', (string)$expiresAt);
+ $this->userConfig->setValueInt($this->userId, Application::APP_ID, 'token_expires_at', $expiresAt, lazy: true);
}
$this->secretService->setEncryptedUserValue($this->userId, 'token', $accessToken);
$this->secretService->setEncryptedUserValue($this->userId, 'refresh_token', $refreshToken);
$username = $this->storeUserInfo();
- $usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0') === '1';
+ $usePopup = $this->appConfig->getAppValueString('use_popup', '0', lazy: true) === '1';
if ($usePopup) {
return new RedirectResponse(
$this->urlGenerator->linkToRoute('integration_google.config.popupSuccessPage', ['username' => $username])
@@ -248,12 +248,12 @@ private function storeUserInfo(): string {
/** @var array{id?:string, name?:string} $info */
$info = $this->googleApiService->request($this->userId, 'oauth2/v1/userinfo', ['alt' => 'json']);
if (isset($info['name'], $info['id'])) {
- $this->config->setUserValue($this->userId, Application::APP_ID, 'user_id', $info['id']);
- $this->config->setUserValue($this->userId, Application::APP_ID, 'user_name', $info['name']);
+ $this->userConfig->setValueString($this->userId, Application::APP_ID, 'user_id', $info['id'], lazy: true);
+ $this->userConfig->setValueString($this->userId, Application::APP_ID, 'user_name', $info['name'], lazy: true);
return $info['name'];
} else {
- $this->config->setUserValue($this->userId, Application::APP_ID, 'user_id', '');
- $this->config->setUserValue($this->userId, Application::APP_ID, 'user_name', '');
+ $this->userConfig->setValueString($this->userId, Application::APP_ID, 'user_id', '', lazy: true);
+ $this->userConfig->setValueString($this->userId, Application::APP_ID, 'user_name', '', lazy: true);
return '';
}
}
diff --git a/lib/Controller/GoogleAPIController.php b/lib/Controller/GoogleAPIController.php
index b99bb785..1cf88d50 100644
--- a/lib/Controller/GoogleAPIController.php
+++ b/lib/Controller/GoogleAPIController.php
@@ -19,7 +19,7 @@
use OCA\Google\Service\SecretService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\DataResponse;
-use OCP\IConfig;
+use OCP\Config\IUserConfig;
use OCP\IRequest;
class GoogleAPIController extends Controller {
@@ -29,7 +29,7 @@ class GoogleAPIController extends Controller {
public function __construct(
string $appName,
IRequest $request,
- private IConfig $config,
+ private IUserConfig $userConfig,
private GoogleContactsAPIService $googleContactsAPIService,
private GoogleDriveAPIService $googleDriveAPIService,
private GoogleCalendarAPIService $googleCalendarAPIService,
@@ -50,10 +50,10 @@ public function getImportDriveInformation(): DataResponse {
return new DataResponse([], 400);
}
return new DataResponse([
- 'importing_drive' => $this->config->getUserValue($this->userId, Application::APP_ID, 'importing_drive') === '1',
- 'last_drive_import_timestamp' => (int)$this->config->getUserValue($this->userId, Application::APP_ID, 'last_drive_import_timestamp', '0'),
- 'nb_imported_files' => (int)$this->config->getUserValue($this->userId, Application::APP_ID, 'nb_imported_files', '0'),
- 'drive_imported_size' => (int)$this->config->getUserValue($this->userId, Application::APP_ID, 'drive_imported_size', '0'),
+ 'importing_drive' => $this->userConfig->getValueString($this->userId, Application::APP_ID, 'importing_drive', lazy: true) === '1',
+ 'last_drive_import_timestamp' => $this->userConfig->getValueInt($this->userId, Application::APP_ID, 'last_drive_import_timestamp', lazy: true),
+ 'nb_imported_files' => $this->userConfig->getValueInt($this->userId, Application::APP_ID, 'nb_imported_files', lazy: true),
+ 'drive_imported_size' => $this->userConfig->getValueInt($this->userId, Application::APP_ID, 'drive_imported_size', lazy: true),
]);
}
diff --git a/lib/Migration/Version03001001Date20241111105515.php b/lib/Migration/Version03001001Date20241111105515.php
index 11679bcd..cc8130c0 100644
--- a/lib/Migration/Version03001001Date20241111105515.php
+++ b/lib/Migration/Version03001001Date20241111105515.php
@@ -10,8 +10,8 @@
use Closure;
use OCA\Google\AppInfo\Application;
+use OCP\AppFramework\Services\IAppConfig;
use OCP\DB\QueryBuilder\IQueryBuilder;
-use OCP\IConfig;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
@@ -20,7 +20,7 @@
class Version03001001Date20241111105515 extends SimpleMigrationStep {
public function __construct(
- private IConfig $config,
+ private IAppConfig $appConfig,
private IDBConnection $connection,
private ICrypto $crypto,
) {
@@ -34,11 +34,11 @@ public function __construct(
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
// migrate api credentials in app config
foreach (['client_id', 'client_secret'] as $key) {
- $value = $this->config->getAppValue(Application::APP_ID, $key);
+ $value = $this->appConfig->getAppValueString($key, '');
if ($value === '') {
continue;
}
- $this->config->setAppValue(Application::APP_ID, $key, $this->crypto->encrypt($value));
+ $this->appConfig->setAppValueString($key, $this->crypto->encrypt($value));
}
// user tokens
diff --git a/lib/Migration/Version04003001Date20251022113940.php b/lib/Migration/Version04003001Date20251022113940.php
new file mode 100644
index 00000000..8e918888
--- /dev/null
+++ b/lib/Migration/Version04003001Date20251022113940.php
@@ -0,0 +1,41 @@
+appConfig->getAppValueString($key, lazy: true);
+ if ($value === '') {
+ continue;
+ }
+ $value = $this->crypto->decrypt($value);
+ $this->appConfig->setAppValueString($key, $value, lazy: true, sensitive: true);
+ }
+ }
+}
diff --git a/lib/Service/GoogleAPIService.php b/lib/Service/GoogleAPIService.php
index 99bff192..ee2b6cc8 100644
--- a/lib/Service/GoogleAPIService.php
+++ b/lib/Service/GoogleAPIService.php
@@ -18,9 +18,10 @@
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\ServerException;
use OCA\Google\AppInfo\Application;
+use OCP\AppFramework\Services\IAppConfig;
+use OCP\Config\IUserConfig;
use OCP\Http\Client\IClientService;
use OCP\Http\Client\IResponse;
-use OCP\IConfig;
use OCP\IL10N;
use OCP\Notification\IManager as INotificationManager;
use Psr\Log\LoggerInterface;
@@ -37,7 +38,8 @@ public function __construct(
string $appName,
private LoggerInterface $logger,
private IL10N $l10n,
- private IConfig $config,
+ private IAppConfig $appConfig,
+ private IUserConfig $userConfig,
private INotificationManager $notificationManager,
IClientService $clientService,
private SecretService $secretService,
@@ -353,10 +355,9 @@ public function simpleDownload(string $userId, string $url, $resource, array $pa
private function checkTokenExpiration(string $userId): void {
$refreshToken = $this->secretService->getEncryptedUserValue($userId, 'refresh_token');
- $expireAt = $this->config->getUserValue($userId, Application::APP_ID, 'token_expires_at');
- if ($refreshToken !== '' && $expireAt !== '') {
+ $expireAt = $this->userConfig->getValueInt($userId, Application::APP_ID, 'token_expires_at', lazy: true);
+ if ($refreshToken !== '' && $expireAt !== 0) {
$nowTs = (new DateTime())->getTimestamp();
- $expireAt = (int)$expireAt;
// if token expires in less than 2 minutes or has already expired
if ($nowTs > $expireAt - 120) {
$this->refreshToken($userId);
@@ -367,8 +368,8 @@ private function checkTokenExpiration(string $userId): void {
public function refreshToken(string $userId): array {
$this->logger->debug('Trying to REFRESH the access token', ['app' => Application::APP_ID]);
$refreshToken = $this->secretService->getEncryptedUserValue($userId, 'refresh_token');
- $clientID = $this->secretService->getEncryptedAppValue('client_id');
- $clientSecret = $this->secretService->getEncryptedAppValue('client_secret');
+ $clientID = $this->appConfig->getAppValueString('client_id', lazy: true);
+ $clientSecret = $this->appConfig->getAppValueString('client_secret', lazy: true);
$result = $this->requestOAuthAccessToken([
'client_id' => $clientID,
'client_secret' => $clientSecret,
@@ -382,7 +383,7 @@ public function refreshToken(string $userId): array {
if (isset($result['expires_in'])) {
$nowTs = (new DateTime())->getTimestamp();
$expiresAt = $nowTs + (int)$result['expires_in'];
- $this->config->setUserValue($userId, Application::APP_ID, 'token_expires_at', $expiresAt);
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'token_expires_at', $expiresAt, lazy: true);
}
} else {
$responseTxt = json_encode($result);
diff --git a/lib/Service/GoogleCalendarAPIService.php b/lib/Service/GoogleCalendarAPIService.php
index 87a781b5..e56b2056 100644
--- a/lib/Service/GoogleCalendarAPIService.php
+++ b/lib/Service/GoogleCalendarAPIService.php
@@ -18,7 +18,7 @@
use Generator;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\Google\AppInfo\Application;
-use OCP\IConfig;
+use OCP\Config\IUserConfig;
use OCP\IL10N;
use Ortic\ColorConverter\Color;
use Ortic\ColorConverter\Colors\Named;
@@ -45,7 +45,7 @@ public function __construct(
private IL10N $l10n,
private CalDavBackend $caldavBackend,
private GoogleAPIService $googleApiService,
- private IConfig $config,
+ private IUserConfig $userConfig,
) {
$this->utcTimezone = new DateTimeZone('-0000');
}
@@ -330,7 +330,7 @@ public function importCalendar(string $userId, string $calId, string $calName, ?
}
date_default_timezone_set('UTC');
- $allEvents = $this->config->getUserValue($userId, Application::APP_ID, 'consider_all_events', '1') === '1';
+ $allEvents = $this->userConfig->getValueString($userId, Application::APP_ID, 'consider_all_events', '1', lazy: true) === '1';
$eventsGenerator = $this->getCalendarEvents($userId, $calId, $allEvents);
// Normal events
diff --git a/lib/Service/GoogleContactsAPIService.php b/lib/Service/GoogleContactsAPIService.php
index aaba6d85..dbac7824 100644
--- a/lib/Service/GoogleContactsAPIService.php
+++ b/lib/Service/GoogleContactsAPIService.php
@@ -17,8 +17,8 @@
use Generator;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\Google\AppInfo\Application;
+use OCP\Config\IUserConfig;
use OCP\Contacts\IManager as IContactManager;
-use OCP\IConfig;
use Psr\Log\LoggerInterface;
use Sabre\VObject\Component\VCard;
use Throwable;
@@ -34,7 +34,7 @@ public function __construct(
private IContactManager $contactsManager,
private CardDavBackend $cdBackend,
private GoogleAPIService $googleApiService,
- private IConfig $config,
+ private IUserConfig $userConfig,
) {
}
@@ -85,7 +85,7 @@ public function getContactNumber(string $userId): array {
return $contacts;
}
$result['nbContacts'] = $contacts['totalItems'] ?? 0;
- $scopes = $this->config->getUserValue($userId, Application::APP_ID, 'user_scopes', '{}');
+ $scopes = $this->userConfig->getValueString($userId, Application::APP_ID, 'user_scopes', '{}', lazy: true);
$scopes = json_decode($scopes, true);
if (isset($scopes['can_access_other_contacts']) && $scopes['can_access_other_contacts'] === 1) {
$params = [
@@ -205,7 +205,7 @@ public function importContacts(string $userId, ?string $uri, int $key, ?string $
}
$existingAddressBook = $addressBook;
}
- $otherContacts = $this->config->getUserValue($userId, Application::APP_ID, 'consider_other_contacts', '0') === '1';
+ $otherContacts = $this->userConfig->getValueString($userId, Application::APP_ID, 'consider_other_contacts', '0', lazy: true) === '1';
$groupsById = $this->getContactGroupsById($userId);
$contacts = $this->getContactList($userId, $otherContacts);
$nbAdded = 0;
diff --git a/lib/Service/GoogleDriveAPIService.php b/lib/Service/GoogleDriveAPIService.php
index a2cd341a..30aacf34 100644
--- a/lib/Service/GoogleDriveAPIService.php
+++ b/lib/Service/GoogleDriveAPIService.php
@@ -25,7 +25,6 @@
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
-use OCP\IConfig;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
use OCP\PreConditionNotMetException;
@@ -48,7 +47,6 @@ class GoogleDriveAPIService {
public function __construct(
string $appName,
private LoggerInterface $logger,
- private IConfig $config,
private IUserConfig $userConfig,
private IRootFolder $root,
private IJobList $jobList,
@@ -63,7 +61,7 @@ public function __construct(
* @return array
*/
public function getDriveSize(string $userId): array {
- $considerSharedFiles = $this->config->getUserValue($userId, Application::APP_ID, 'consider_shared_files', '0') === '1';
+ $considerSharedFiles = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'consider_shared_files', '0', lazy:true) === '1';
$params = [
'fields' => '*',
];
@@ -113,13 +111,13 @@ public function getDriveSize(string $userId): array {
* @throws PreConditionNotMetException
*/
public function startImportDrive(string $userId): array {
- $targetPath = $this->config->getUserValue($userId, Application::APP_ID, 'drive_output_dir', '/Google Drive');
+ $targetPath = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'drive_output_dir', '/Google Drive', lazy:true);
$targetPath = $targetPath ?: '/Google Drive';
- $considerSharedFiles = $this->config->getUserValue($userId, Application::APP_ID, 'consider_shared_files', '0') === '1';
- $targetSharedPath = $this->config->getUserValue($userId, Application::APP_ID, 'drive_shared_with_me_output_dir', '/Google Drive/Shared with me');
+ $considerSharedFiles = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'consider_shared_files', '0', lazy:true) === '1';
+ $targetSharedPath = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'drive_shared_with_me_output_dir', '/Google Drive/Shared with me', lazy:true);
$targetSharedPath = $targetSharedPath ?: '/Google Drive/Shared with me';
- $alreadyImporting = $this->config->getUserValue($userId, Application::APP_ID, 'importing_drive', '0') === '1';
+ $alreadyImporting = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'importing_drive', '0', lazy:true) === '1';
if ($alreadyImporting) {
return ['targetPath' => $targetPath];
}
@@ -145,11 +143,11 @@ public function startImportDrive(string $userId): array {
}
}
- $this->config->setUserValue($userId, Application::APP_ID, 'importing_drive', '1');
- $this->config->setUserValue($userId, Application::APP_ID, 'nb_imported_files', '0');
- $this->config->setUserValue($userId, Application::APP_ID, 'drive_imported_size', '0');
- $this->config->setUserValue($userId, Application::APP_ID, 'last_drive_import_timestamp', '0');
- $this->config->deleteUserValue($userId, Application::APP_ID, 'directory_progress');
+ $this->userConfig->setValueString($userId, Application::APP_ID, 'importing_drive', '1', lazy: true);
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'nb_imported_files', 0, lazy: true);
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'drive_imported_size', 0, lazy: true);
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'last_drive_import_timestamp', 0, lazy: true);
+ $this->userConfig->deleteUserConfig($userId, Application::APP_ID, 'directory_progress');
$this->jobList->add(ImportDriveJob::class, ['user_id' => $userId]);
return ['targetPath' => $targetPath];
@@ -171,28 +169,28 @@ public function importDriveJob(string $userId): void {
$this->userScopeService->setUserScope($userId);
$this->userScopeService->setFilesystemScope($userId);
- $importingDrive = $this->config->getUserValue($userId, Application::APP_ID, 'importing_drive', '0') === '1';
+ $importingDrive = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'importing_drive', '0', lazy:true) === '1';
if (!$importingDrive) {
return;
}
- $jobRunning = $this->config->getUserValue($userId, Application::APP_ID, 'drive_import_running', '0') === '1';
+ $jobRunning = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'drive_import_running', '0', lazy:true) === '1';
$nowTs = (new DateTime())->getTimestamp();
if ($jobRunning) {
- $lastJobStart = $this->config->getUserValue($userId, Application::APP_ID, 'drive_import_job_last_start');
- if ($lastJobStart !== '' && ($nowTs - intval($lastJobStart) < Application::IMPORT_JOB_TIMEOUT)) {
+ $lastJobStart = $this->userConfig->getValueInt($userId, APPLICATION::APP_ID, 'drive_import_job_last_start', lazy:true);
+ if ($lastJobStart !== 0 && ($nowTs - intval($lastJobStart) < Application::IMPORT_JOB_TIMEOUT)) {
$this->logger->info('Last job execution (' . strval($nowTs - intval($lastJobStart)) . ') is less than ' . strval(Application::IMPORT_JOB_TIMEOUT) . ' seconds ago, delaying execution');
// last job has started less than an hour ago => we consider it can still be running
$this->jobList->add(ImportDriveJob::class, ['user_id' => $userId]);
return;
}
}
- $this->config->setUserValue($userId, Application::APP_ID, 'drive_import_running', '1');
- $this->config->setUserValue($userId, Application::APP_ID, 'drive_import_job_last_start', strval($nowTs));
+ $this->userConfig->setValueString($userId, Application::APP_ID, 'drive_import_running', '1', lazy: true);
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'drive_import_job_last_start', $nowTs, lazy: true);
// import batch of files
- $targetPath = $this->config->getUserValue($userId, Application::APP_ID, 'drive_output_dir', '/Google Drive');
+ $targetPath = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'drive_output_dir', '/Google Drive', lazy:true);
$targetPath = $targetPath ?: '/Google Drive';
- $targetSharedPath = $this->config->getUserValue($userId, Application::APP_ID, 'drive_shared_with_me_output_dir', '/Google Drive/Shared with me');
+ $targetSharedPath = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'drive_shared_with_me_output_dir', '/Google Drive/Shared with me', lazy:true);
$targetSharedPath = $targetSharedPath ?: '/Google Drive/Shared with me';
// check if target paths are suitable
@@ -200,7 +198,7 @@ public function importDriveJob(string $userId): void {
$targetSharedPath = $this->getNonSharedTargetPath($userId, $targetSharedPath);
// get progress
- $directoryProgressStr = $this->config->getUserValue($userId, Application::APP_ID, 'directory_progress', '[]');
+ $directoryProgressStr = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'directory_progress', '[]', lazy:true);
$directoryProgress = ($directoryProgressStr === '' || $directoryProgressStr === '[]')
? []
: json_decode($directoryProgressStr, true);
@@ -217,7 +215,7 @@ public function importDriveJob(string $userId): void {
}
if (isset($result['error']) || (isset($result['finished']) && $result['finished'])) {
if (isset($result['finished']) && $result['finished']) {
- $nbImported = (int)$this->config->getUserValue($userId, Application::APP_ID, 'nb_imported_files', '0');
+ $nbImported = $this->userConfig->getValueInt($userId, APPLICATION::APP_ID, 'nb_imported_files', lazy:true);
$this->googleApiService->sendNCNotification($userId, 'import_drive_finished', [
'nbImported' => $nbImported,
'targetPath' => $targetPath,
@@ -226,18 +224,18 @@ public function importDriveJob(string $userId): void {
if (isset($result['error'])) {
$this->logger->error('Google Drive import error: ' . $result['error'], ['app' => Application::APP_ID]);
}
- $this->config->setUserValue($userId, Application::APP_ID, 'importing_drive', '0');
- $this->config->setUserValue($userId, Application::APP_ID, 'nb_imported_files', '0');
- $this->config->setUserValue($userId, Application::APP_ID, 'drive_imported_size', '0');
- $this->config->setUserValue($userId, Application::APP_ID, 'last_drive_import_timestamp', '0');
- $this->config->deleteUserValue($userId, Application::APP_ID, 'directory_progress');
+ $this->userConfig->setValueString($userId, Application::APP_ID, 'importing_drive', '0', lazy: true);
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'nb_imported_files', 0, lazy: true);
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'drive_imported_size', 0, lazy: true);
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'last_drive_import_timestamp', 0, lazy: true);
+ $this->userConfig->deleteUserConfig($userId, Application::APP_ID, 'directory_progress');
} else {
- $this->config->setUserValue($userId, Application::APP_ID, 'directory_progress', json_encode($directoryProgress));
+ $this->userConfig->setValueString($userId, Application::APP_ID, 'directory_progress', json_encode($directoryProgress), lazy: true);
$ts = (new DateTime())->getTimestamp();
- $this->config->setUserValue($userId, Application::APP_ID, 'last_drive_import_timestamp', $ts);
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'last_drive_import_timestamp', $ts, lazy: true);
$this->jobList->add(ImportDriveJob::class, ['user_id' => $userId]);
}
- $this->config->setUserValue($userId, Application::APP_ID, 'drive_import_running', '0');
+ $this->userConfig->setValueString($userId, Application::APP_ID, 'drive_import_running', '0', lazy: true);
}
/**
@@ -255,7 +253,7 @@ public function importFiles(
string $userId, string $targetPath, string $targetSharedPath,
?int $maxDownloadSize = null, array &$directoryProgress = [],
): array {
- $considerSharedFiles = $this->config->getUserValue($userId, Application::APP_ID, 'consider_shared_files', '0') === '1';
+ $considerSharedFiles = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'consider_shared_files', '0', lazy:true) === '1';
// create root folder(s)
$userFolder = $this->root->getUserFolder($userId);
@@ -375,7 +373,7 @@ public function importFiles(
*/
public function hasBeenCancelled(string $userId): bool {
$this->userConfig->clearCache($userId);
- return $this->config->getUserValue($userId, Application::APP_ID, 'importing_drive', '0') === '0';
+ return $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'importing_drive', '0', lazy:true) === '0';
}
/**
@@ -646,7 +644,7 @@ private function getFileName(array $fileItem, string $userId, bool $hasNameConfl
* @return string User's preferred document format
*/
private function getUserDocumentFormat(string $userId): string {
- $documentFormat = $this->config->getUserValue($userId, Application::APP_ID, 'document_format', 'openxml');
+ $documentFormat = $this->userConfig->getValueString($userId, APPLICATION::APP_ID, 'document_format', 'openxml', lazy:true);
if (!in_array($documentFormat, ['openxml', 'opendoc'])) {
$documentFormat = 'openxml';
}
@@ -846,8 +844,8 @@ private function recursivelyCheckParentOwnership(string $rootId, array $director
*/
private function retrieveFiles(string $userId, string $dirId, string $query, bool $considerSharedFiles, Folder $rootImportFolder, ?Folder $rootSharedWithMeImportFolder, array $directoriesById, array $sharedDirectoriesById, ?int $maxDownloadSize, string $targetPath, bool $allowParents = true): ?array {
$lastCancelCheck = time();
- $alreadyImported = (int)$this->config->getUserValue($userId, Application::APP_ID, 'nb_imported_files', '0');
- $alreadyImportedSize = (int)$this->config->getUserValue($userId, Application::APP_ID, 'drive_imported_size', '0');
+ $alreadyImported = $this->userConfig->getValueInt($userId, APPLICATION::APP_ID, 'nb_imported_files', lazy:true);
+ $alreadyImportedSize = $this->userConfig->getValueInt($userId, APPLICATION::APP_ID, 'drive_imported_size', lazy:true);
$conflictingIds = $this->getFilesWithNameConflict($userId, $query, $considerSharedFiles);
$params = [
@@ -921,9 +919,9 @@ private function retrieveFiles(string $userId, string $dirId, string $query, boo
if (!is_null($size)) {
$alreadyImported++;
- $this->config->setUserValue($userId, Application::APP_ID, 'nb_imported_files', strval($alreadyImported));
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'nb_imported_files', $alreadyImported, lazy: true);
$alreadyImportedSize += $size;
- $this->config->setUserValue($userId, Application::APP_ID, 'drive_imported_size', strval($alreadyImportedSize));
+ $this->userConfig->setValueInt($userId, Application::APP_ID, 'drive_imported_size', $alreadyImportedSize, lazy: true);
if ($maxDownloadSize !== null && $alreadyImportedSize > $maxDownloadSize) {
return [
'targetPath' => $targetPath,
diff --git a/lib/Service/SecretService.php b/lib/Service/SecretService.php
index bcb52f35..1289fb71 100644
--- a/lib/Service/SecretService.php
+++ b/lib/Service/SecretService.php
@@ -3,15 +3,13 @@
namespace OCA\Google\Service;
use OCA\Google\AppInfo\Application;
-use OCP\IConfig;
-use OCP\IUserManager;
+use OCP\Config\IUserConfig;
use OCP\PreConditionNotMetException;
use OCP\Security\ICrypto;
class SecretService {
public function __construct(
- private IConfig $config,
- private IUserManager $userManager,
+ private IUserConfig $userConfig,
private ICrypto $crypto,
) {
}
@@ -25,11 +23,11 @@ public function __construct(
*/
public function setEncryptedUserValue(string $userId, string $key, string $value): void {
if ($value === '') {
- $this->config->setUserValue($userId, Application::APP_ID, $key, '');
+ $this->userConfig->setValueString($userId, Application::APP_ID, $key, '', lazy: true);
return;
}
$encryptedValue = $this->crypto->encrypt($value);
- $this->config->setUserValue($userId, Application::APP_ID, $key, $encryptedValue);
+ $this->userConfig->setValueString($userId, Application::APP_ID, $key, $encryptedValue, lazy: true);
}
/**
@@ -39,34 +37,7 @@ public function setEncryptedUserValue(string $userId, string $key, string $value
* @throws \Exception
*/
public function getEncryptedUserValue(string $userId, string $key): string {
- $storedValue = $this->config->getUserValue($userId, Application::APP_ID, $key);
- if ($storedValue === '') {
- return '';
- }
- return $this->crypto->decrypt($storedValue);
- }
-
- /**
- * @param string $key
- * @param string $value
- * @return void
- */
- public function setEncryptedAppValue(string $key, string $value): void {
- if ($value === '') {
- $this->config->setAppValue(Application::APP_ID, $key, '');
- return;
- }
- $encryptedValue = $this->crypto->encrypt($value);
- $this->config->setAppValue(Application::APP_ID, $key, $encryptedValue);
- }
-
- /**
- * @param string $key
- * @return string
- * @throws \Exception
- */
- public function getEncryptedAppValue(string $key): string {
- $storedValue = $this->config->getAppValue(Application::APP_ID, $key);
+ $storedValue = $this->userConfig->getValueString($userId, Application::APP_ID, $key, lazy: true);
if ($storedValue === '') {
return '';
}
diff --git a/lib/Service/Utils/FileUtils.php b/lib/Service/Utils/FileUtils.php
index f5cea353..231cc2fa 100644
--- a/lib/Service/Utils/FileUtils.php
+++ b/lib/Service/Utils/FileUtils.php
@@ -2,11 +2,7 @@
namespace OCA\Google\Service\Utils;
-use OCP\Files\EmptyFileNameException;
-use OCP\Files\FileNameTooLongException;
-use OCP\Files\InvalidCharacterInPathException;
-use OCP\Files\InvalidDirectoryException;
-use OCP\Files\ReservedWordException;
+use OCP\Files\IFilenameValidator;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LoggerInterface;
@@ -14,8 +10,7 @@
final class FileUtils {
public function __construct(
- private \OCP\Files\IFilenameValidator $validator,
- private \OCP\IConfig $config,
+ private IFilenameValidator $validator,
private LoggerInterface $logger,
) {
}
@@ -25,111 +20,19 @@ public function __construct(
*
* @param string $filename The original filename to sanitize.
* @param string $id A unique ID to append if necessary to ensure uniqueness.
- * @param int $recursionDepth The current recursion depth (used to prevent infinite loops).
- * @param string|null $originalFilename The original filename for logging.
* @return string The sanitized and validated filename.
*/
public function sanitizeFilename(
string $filename,
string $id,
- int $recursionDepth = 0,
- ?string $originalFilename = null,
): string {
- if ($recursionDepth > 15) {
- $filename = 'Untitled_' . $id;
- $this->logger->warning('Maximum recursion depth reached while sanitizing filename: ' . ($originalFilename ?? $filename) . ' renaming to ' . $filename);
- return $filename;
- }
-
- if ($originalFilename === null) {
- $originalFilename = $filename;
- }
-
- // Use Nextcloud 32+ validator if available
- if (version_compare($this->config->getSystemValueString('version', '0.0.0'), '32.0.0', '>=')) {
- $this->logger->debug('Using Nextcloud 32+ filename validator for sanitization.');
- try {
- return $this->validator->sanitizeFilename($filename);
- } catch (\InvalidArgumentException|NotFoundExceptionInterface|ContainerExceptionInterface $exception) {
- $this->logger->error('Unable to sanitize filename: ' . $filename, ['exception' => $exception]);
- return 'Untitled_' . $id;
- }
- } else {
- $this->logger->debug('Using legacy filename sanitization method.');
- }
-
- // Trim whitespace and trailing dots
- $filename = rtrim(trim($filename), '.');
-
- // Append ID if needed
- if ($originalFilename !== $filename && strpos($filename, $id) === false) {
- $filename = self::appendIdBeforeExtension($filename, $id);
- }
-
- // Enforce max length
- $maxLength = 254;
- if (mb_strlen($filename) > $maxLength) {
- $filename = self::truncateAndAppendId($filename, $id, $maxLength);
- }
+ // Use Nextcloud 32+ validator
try {
- $this->validator->validateFilename($filename);
- if ($recursionDepth > 0) {
- $this->logger->info('Filename sanitized successfully: "' . $filename . '" (original: "' . $originalFilename . '")');
- }
- return $filename;
- } catch (\Throwable $exception) {
- $this->logger->warning('Exception during filename validation: ' . $filename, ['exception' => $exception]);
- $filename = self::handleFilenameException($filename, $id, $exception, $this->logger);
- if (strpos($filename, $id) === false) {
- $filename = self::appendIdBeforeExtension($filename, $id);
- }
- return $this->sanitizeFilename($filename, $id, $recursionDepth + 1, $originalFilename);
- }
- }
-
- private static function appendIdBeforeExtension(string $filename, string $id): string {
- $pathInfo = pathinfo($filename);
- if (isset($pathInfo['extension'])) {
- return $pathInfo['filename'] . '_' . $id . '.' . $pathInfo['extension'];
- }
- return $filename . '_' . $id;
- }
-
- private static function truncateAndAppendId(string $filename, string $id, int $maxLength): string {
- $pathInfo = pathinfo($filename);
- $baseLength = $maxLength - mb_strlen($id) - 2;
- if (isset($pathInfo['extension'])) {
- $baseLength -= mb_strlen($pathInfo['extension']);
- return mb_substr($pathInfo['filename'], 0, $baseLength) . '_' . $id . '.' . $pathInfo['extension'];
- }
- return mb_substr($filename, 0, $baseLength) . '_' . $id;
- }
-
- private static function handleFilenameException(string $filename, string $id, \Throwable $exception, LoggerInterface $logger): string {
- if ($exception instanceof FileNameTooLongException) {
- return mb_substr($filename, 0, 254 - mb_strlen($id) - 2);
- }
- if ($exception instanceof EmptyFileNameException) {
- return 'Untitled';
- }
- if ($exception instanceof InvalidCharacterInPathException) {
- if (preg_match('/"(.*?)"/', $exception->getMessage(), $matches)) {
- $invalidChars = array_merge(str_split($matches[1]), ['"']);
- return str_replace($invalidChars, '-', $filename);
- }
- }
- if ($exception instanceof InvalidDirectoryException) {
- $logger->error('Invalid directory detected in filename: ' . $exception->getMessage());
- return 'Untitled';
- }
- if ($exception instanceof ReservedWordException) {
- if (preg_match('/"(.*?)"/', $exception->getMessage(), $matches)) {
- $reservedWord = $matches[1];
- return str_ireplace($reservedWord, '-' . $reservedWord . '-', $filename);
- }
+ return $this->validator->sanitizeFilename($filename);
+ } catch (\InvalidArgumentException|NotFoundExceptionInterface|ContainerExceptionInterface $exception) {
+ $this->logger->error('Unable to sanitize filename: ' . $filename, ['exception' => $exception]);
+ return 'Untitled_' . $id;
}
- $logger->error('Unknown exception encountered during filename sanitization: ' . $filename);
- return 'Untitled';
}
}
diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php
index 176796af..c4e2c5ca 100644
--- a/lib/Settings/Admin.php
+++ b/lib/Settings/Admin.php
@@ -3,18 +3,16 @@
namespace OCA\Google\Settings;
use OCA\Google\AppInfo\Application;
-use OCA\Google\Service\SecretService;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Services\IInitialState;
-use OCP\IConfig;
use OCP\Settings\ISettings;
class Admin implements ISettings {
public function __construct(
- private IConfig $config,
+ private IAppConfig $appConfig,
private IInitialState $initialStateService,
- private SecretService $secretService,
) {
}
@@ -22,9 +20,9 @@ public function __construct(
* @return TemplateResponse
*/
public function getForm(): TemplateResponse {
- $clientID = $this->secretService->getEncryptedAppValue('client_id');
- $clientSecret = $this->secretService->getEncryptedAppValue('client_secret');
- $usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0');
+ $clientID = $this->appConfig->getAppValueString('client_id', lazy: true);
+ $clientSecret = $this->appConfig->getAppValueString('client_secret', lazy: true);
+ $usePopup = $this->appConfig->getAppValueString('use_popup', '0', lazy: true);
$adminConfig = [
'client_id' => $clientID,
diff --git a/lib/Settings/Personal.php b/lib/Settings/Personal.php
index dfbf5a0a..50c85112 100644
--- a/lib/Settings/Personal.php
+++ b/lib/Settings/Personal.php
@@ -7,12 +7,13 @@
use OCA\Google\Service\GoogleAPIService;
use OCA\Google\Service\SecretService;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Services\IInitialState;
+use OCP\Config\IUserConfig;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
-use OCP\IConfig;
use OCP\IUserManager;
use OCP\Settings\ISettings;
use Throwable;
@@ -20,7 +21,8 @@
class Personal implements ISettings {
public function __construct(
- private IConfig $config,
+ private IAppConfig $appConfig,
+ private IUserConfig $userConfig,
private IRootFolder $root,
private IUserManager $userManager,
private IInitialState $initialStateService,
@@ -40,24 +42,24 @@ public function getForm(): TemplateResponse {
if ($this->userId === null) {
return new TemplateResponse(Application::APP_ID, 'personalSettings');
}
- $userName = $this->config->getUserValue($this->userId, Application::APP_ID, 'user_name');
- $driveOutputDir = $this->config->getUserValue($this->userId, Application::APP_ID, 'drive_output_dir', '/Google Drive');
+ $userName = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'user_name', lazy: true);
+ $driveOutputDir = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'drive_output_dir', '/Google Drive', lazy: true);
$driveOutputDir = $driveOutputDir ?: '/Google Drive';
- $driveSharedWithMeOutputDir = $this->config->getUserValue($this->userId, Application::APP_ID, 'drive_shared_with_me_output_dir', '/Google Drive/Shared with me');
+ $driveSharedWithMeOutputDir = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'drive_shared_with_me_output_dir', '/Google Drive/Shared with me', lazy: true);
$driveSharedWithMeOutputDir = $driveSharedWithMeOutputDir ?: '/Google Drive/Shared with me';
- $considerAllEvents = $this->config->getUserValue($this->userId, Application::APP_ID, 'consider_all_events', '1') === '1';
- $considerSharedFiles = $this->config->getUserValue($this->userId, Application::APP_ID, 'consider_shared_files', '0') === '1';
- $considerSharedAlbums = $this->config->getUserValue($this->userId, Application::APP_ID, 'consider_shared_albums', '0') === '1';
- $considerOtherContacts = $this->config->getUserValue($this->userId, Application::APP_ID, 'consider_other_contacts', '0') === '1';
- $documentFormat = $this->config->getUserValue($this->userId, Application::APP_ID, 'document_format', 'openxml');
+ $considerAllEvents = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'consider_all_events', '1', lazy: true) === '1';
+ $considerSharedFiles = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'consider_shared_files', '0', lazy: true) === '1';
+ $considerSharedAlbums = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'consider_shared_albums', '0', lazy: true) === '1';
+ $considerOtherContacts = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'consider_other_contacts', '0', lazy: true) === '1';
+ $documentFormat = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'document_format', 'openxml', lazy: true);
if (!in_array($documentFormat, ['openxml', 'opendoc'])) {
$documentFormat = 'openxml';
}
// for OAuth
- $clientID = $this->secretService->getEncryptedAppValue('client_id');
- $clientSecret = $this->secretService->getEncryptedAppValue('client_secret') !== '';
- $usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0');
+ $clientID = $this->appConfig->getAppValueString('client_id', lazy: true);
+ $clientSecret = $this->appConfig->getAppValueString('client_secret', lazy: true) !== '';
+ $usePopup = $this->appConfig->getAppValueString('use_popup', '0', lazy: true);
// get free space
$userFolder = $this->root->getUserFolder($this->userId);
@@ -71,7 +73,7 @@ public function getForm(): TemplateResponse {
}
// Get scopes of user
- $userScopesString = $this->config->getUserValue($this->userId, Application::APP_ID, 'user_scopes', '{}');
+ $userScopesString = $this->userConfig->getValueString($this->userId, Application::APP_ID, 'user_scopes', '{}', lazy: true);
/** @var bool|null|array $userScopes */
$userScopes = json_decode($userScopesString, true);
if (!is_array($userScopes)) {
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 2b7f586d..a96d5b28 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -16,6 +16,11 @@
+
+
+
+
+
@@ -24,9 +29,6 @@
-
-
-
getStatusCode()]]>
getStatusCode()]]>
@@ -149,19 +151,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-