Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<name>Google integration</name>
<summary>Import Google data into Nextcloud</summary>
<description><![CDATA[Google integration allows you to automatically migrate your Google calendars, contacts, and files into Nextcloud.]]></description>
<version>4.2.0</version>
<version>4.3.0</version>
<licence>agpl</licence>
<author>Julien Veyssier</author>
<namespace>Google</namespace>
Expand All @@ -16,7 +16,7 @@
<bugs>https://github.com/nextcloud/integration_google/issues</bugs>
<screenshot>https://github.com/nextcloud/integration_google/raw/master/img/screenshot1.jpg</screenshot>
<dependencies>
<nextcloud min-version="32" max-version="32"/>
<nextcloud min-version="32" max-version="33"/>
</dependencies>
<settings>
<admin>OCA\Google\Settings\Admin</admin>
Expand Down
48 changes: 24 additions & 24 deletions lib/Controller/ConfigController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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'])) {
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand All @@ -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])
Expand Down Expand Up @@ -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 '';
}
}
Expand Down
12 changes: 6 additions & 6 deletions lib/Controller/GoogleAPIController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
Expand All @@ -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),
]);
}

Expand Down
8 changes: 4 additions & 4 deletions lib/Migration/Version03001001Date20241111105515.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,7 +20,7 @@
class Version03001001Date20241111105515 extends SimpleMigrationStep {

public function __construct(
private IConfig $config,
private IAppConfig $appConfig,
private IDBConnection $connection,
private ICrypto $crypto,
) {
Expand All @@ -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
Expand Down
41 changes: 41 additions & 0 deletions lib/Migration/Version04003001Date20251022113940.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Google\Migration;

use Closure;
use OCP\AppFramework\Services\IAppConfig;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
use OCP\Security\ICrypto;

class Version04003001Date20251022113940 extends SimpleMigrationStep {

public function __construct(
private IAppConfig $appConfig,
private ICrypto $crypto,
) {
}

/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
*/
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
// migrate api credentials in app config to sensitive instead of manually encrypting and decrypting
foreach (['client_id', 'client_secret'] as $key) {
$value = $this->appConfig->getAppValueString($key, lazy: true);
if ($value === '') {
continue;
}
$value = $this->crypto->decrypt($value);
$this->appConfig->setAppValueString($key, $value, lazy: true, sensitive: true);
}
}
}
17 changes: 9 additions & 8 deletions lib/Service/GoogleAPIService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand All @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions lib/Service/GoogleCalendarAPIService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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');
}
Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions lib/Service/GoogleContactsAPIService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -34,7 +34,7 @@ public function __construct(
private IContactManager $contactsManager,
private CardDavBackend $cdBackend,
private GoogleAPIService $googleApiService,
private IConfig $config,
private IUserConfig $userConfig,
) {
}

Expand Down Expand Up @@ -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 = [
Expand Down Expand Up @@ -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;
Expand Down
Loading