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: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed

- Stop loading most of the app's settings on every request

## 3.3.0 - 2026-10-02

### Added
Expand Down
7 changes: 5 additions & 2 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\AppFramework\Services\IAppConfig;

use OCP\Collaboration\Reference\RenderReferenceEvent;

Expand All @@ -37,20 +38,22 @@ class Application extends App implements IBootstrap {

private ContainerInterface $container;
private IConfig $config;
private IAppConfig $appConfig;

public function __construct(array $urlParams = []) {
parent::__construct(self::APP_ID, $urlParams);

$this->container = $this->getContainer();
$this->config = $this->container->get(IConfig::class);
$this->appConfig = $this->container->get(IAppConfig::class);
}

public function register(IRegistrationContext $context): void {
if ($this->config->getAppValue(self::APP_ID, 'dashboard_enabled', '1') === '1') {
if ($this->appConfig->getAppValueString('dashboard_enabled', '1') === '1') {
$context->registerDashboardWidget(GithubWidget::class);
}

if ($this->config->getAppValue(self::APP_ID, 'issue_notifications_enabled', '1') === '1') {
if ($this->appConfig->getAppValueString('issue_notifications_enabled', '1') === '1') {
$context->registerNotifierService(GitHubNotifier::class);
}

Expand Down
45 changes: 33 additions & 12 deletions lib/Controller/ConfigController.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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\IConfig;
use OCP\IL10N;
Expand All @@ -32,10 +33,27 @@

class ConfigController extends Controller {

/**
* The switches of the admin settings, and whether each one is stored lazily.
* dashboard_enabled and issue_notifications_enabled are read in Application::register(),
* which runs on every request, so they stay non-lazy.
*/
private const ADMIN_SWITCHES = [
'use_popup' => true,
'link_preview_enabled' => true,
'allow_default_link_token_to_anonymous' => true,
'allow_default_link_token_to_guests' => true,
'dashboard_enabled' => false,
'issue_notifications_enabled' => false,
];

private const SECRET_KEYS = ['client_id', 'client_secret', 'default_link_token'];

public function __construct(
string $appName,
IRequest $request,
private IConfig $config,
private IAppConfig $appConfig,
private IURLGenerator $urlGenerator,
private IL10N $l,
private IInitialState $initialStateService,
Expand Down Expand Up @@ -108,13 +126,15 @@ public function setConfig(array $values): DataResponse {
* @return DataResponse
*/
public function setAdminConfig(array $values): DataResponse {
// only the switches, so that a request cannot write a key the server owns, such as "enabled"
foreach ($values as $key => $value) {
if (in_array($key, ['client_id', 'client_secret', 'default_link_token'], true)) {
if (!array_key_exists($key, self::ADMIN_SWITCHES) || !is_string($value)) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
} else {
$this->config->setAppValue(Application::APP_ID, $key, $value);
}
}
foreach ($values as $key => $value) {
$this->appConfig->setAppValueString($key, $value, lazy: self::ADMIN_SWITCHES[$key]);
}
return new DataResponse([]);
}

Expand All @@ -127,14 +147,15 @@ public function setAdminConfig(array $values): DataResponse {
#[PasswordConfirmationRequired]
public function setSensitiveAdminConfig(array $values): DataResponse {
foreach ($values as $key => $value) {
if (in_array($key, ['client_id', 'client_secret', 'default_link_token'], true)) {
$this->secretService->setEncryptedAppValue($key, $value);
if ($key === 'default_link_token') {
$info = $this->githubAPIService->updateLinkTokenUserInfo($value);
return new DataResponse($info);
}
} else {
$this->config->setAppValue(Application::APP_ID, $key, $value);
if (!in_array($key, self::SECRET_KEYS, true) || !is_string($value)) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
}
foreach ($values as $key => $value) {
$this->secretService->setEncryptedAppValue($key, $value);
if ($key === 'default_link_token') {
$info = $this->githubAPIService->updateLinkTokenUserInfo($value);
return new DataResponse($info);
}
}
return new DataResponse([]);
Expand Down Expand Up @@ -184,7 +205,7 @@ public function oauthRedirect(string $code, string $state): RedirectResponse {
$this->config->setUserValue($this->userId, Application::APP_ID, 'token_type', 'oauth');
$userInfo = $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_github.config.popupSuccessPage', [
Expand Down
10 changes: 5 additions & 5 deletions lib/Dashboard/GithubWidget.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@

use OCA\Github\AppInfo\Application;
use OCA\Github\Service\GithubAPIService;
use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Services\IInitialState;
use OCP\Dashboard\IAPIWidget;
use OCP\Dashboard\IButtonWidget;
use OCP\Dashboard\IIconWidget;
use OCP\Dashboard\IOptionWidget;
use OCP\Dashboard\Model\WidgetButton;
use OCP\Dashboard\Model\WidgetOptions;
use OCP\IConfig;
use OCP\IL10N;
use OCP\IURLGenerator;

Expand All @@ -26,7 +26,7 @@ class GithubWidget implements IAPIWidget, IButtonWidget, IIconWidget, IOptionWid

public function __construct(
private IL10N $l10n,
private IConfig $config,
private IAppConfig $appConfig,
private IURLGenerator $urlGenerator,
private IInitialState $initialStateService,
private GithubAPIService $githubAPIService,
Expand Down Expand Up @@ -82,10 +82,10 @@ public function getUrl(): ?string {
* @inheritDoc
*/
public function load(): void {
$clientID = $this->config->getAppValue(Application::APP_ID, 'client_id');
$clientSecret = $this->config->getAppValue(Application::APP_ID, 'client_secret');
$clientID = $this->appConfig->getAppValueString('client_id', lazy: true);
$clientSecret = $this->appConfig->getAppValueString('client_secret', lazy: true);
$oauthPossible = $clientID !== '' && $clientSecret !== '';
$usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0');
$usePopup = $this->appConfig->getAppValueString('use_popup', '0', lazy: true);

$userConfig = [
'oauth_is_possible' => $oauthPossible,
Expand Down
8 changes: 4 additions & 4 deletions lib/Migration/Version030010Date20241002015812.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use Closure;
use OCA\Github\AppInfo\Application;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
use OCP\IAppConfig;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
Expand All @@ -22,7 +22,7 @@ class Version030010Date20241002015812 extends SimpleMigrationStep {
public function __construct(
private IDBConnection $connection,
private ICrypto $crypto,
private IConfig $config,
private IAppConfig $appConfig,
) {
}

Expand All @@ -34,10 +34,10 @@ public function __construct(
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
// client_id, client_secret, default_link_token
foreach (['client_id', 'client_secret', 'default_link_token'] as $key) {
$value = $this->config->getAppValue(Application::APP_ID, $key);
$value = $this->appConfig->getValueString(Application::APP_ID, $key, lazy: true);
if ($value !== '') {
$encryptedValue = $this->crypto->encrypt($value);
$this->config->setAppValue(Application::APP_ID, $key, $encryptedValue);
$this->appConfig->setValueString(Application::APP_ID, $key, $encryptedValue, lazy: true);
}
}

Expand Down
58 changes: 58 additions & 0 deletions lib/Migration/Version030301Date20261021102507.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Github\Migration;

use Closure;
use OCA\Github\AppInfo\Application;
use OCP\DB\ISchemaWrapper;
use OCP\IAppConfig;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

class Version030301Date20261021102507 extends SimpleMigrationStep {

/**
* The app config keys that are only read by the app's own pages, settings, providers,
* OAuth flow and API requests. dashboard_enabled and issue_notifications_enabled are
* read on every request in Application::register() and stay non-lazy.
*/
private const LAZY_APP_CONFIG_KEYS = [
'client_id',
'client_secret',
'default_link_token',
'use_popup',
'link_preview_enabled',
'allow_default_link_token_to_anonymous',
'allow_default_link_token_to_guests',
'user_name',
'user_displayname',
];

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

/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
*
* @return null|ISchemaWrapper
*/
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
// mark the values stored as non-lazy by earlier versions as lazy
foreach (self::LAZY_APP_CONFIG_KEYS as $key) {
$this->appConfig->updateLazy(Application::APP_ID, $key, true);
}

return null;
}
}
4 changes: 3 additions & 1 deletion lib/Reference/GithubCodeReferenceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use OC\Collaboration\Reference\ReferenceManager;
use OCA\Github\AppInfo\Application;
use OCA\Github\Service\GithubAPIService;
use OCP\AppFramework\Services\IAppConfig;
use OCP\Collaboration\Reference\ADiscoverableReferenceProvider;
use OCP\Collaboration\Reference\IReference;
use OCP\Collaboration\Reference\Reference;
Expand All @@ -24,6 +25,7 @@ class GithubCodeReferenceProvider extends ADiscoverableReferenceProvider {
public function __construct(
private GithubAPIService $githubAPIService,
private IConfig $config,
private IAppConfig $appConfig,
private IL10N $l10n,
private IURLGenerator $urlGenerator,
private ReferenceManager $referenceManager,
Expand Down Expand Up @@ -71,7 +73,7 @@ public function matchReference(string $referenceText): bool {
return false;
}
}
$adminLinkPreviewEnabled = $this->config->getAppValue(Application::APP_ID, 'link_preview_enabled', '1') === '1';
$adminLinkPreviewEnabled = $this->appConfig->getAppValueString('link_preview_enabled', '1', lazy: true) === '1';
if (!$adminLinkPreviewEnabled) {
return false;
}
Expand Down
4 changes: 3 additions & 1 deletion lib/Reference/GithubIssuePrReferenceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use OC\Collaboration\Reference\ReferenceManager;
use OCA\Github\AppInfo\Application;
use OCA\Github\Service\GithubAPIService;
use OCP\AppFramework\Services\IAppConfig;
use OCP\Collaboration\Reference\ADiscoverableReferenceProvider;
use OCP\Collaboration\Reference\IReference;
use OCP\Collaboration\Reference\ISearchableReferenceProvider;
Expand All @@ -31,6 +32,7 @@ class GithubIssuePrReferenceProvider extends ADiscoverableReferenceProvider impl
public function __construct(
private GithubAPIService $githubAPIService,
private IConfig $config,
private IAppConfig $appConfig,
private IL10N $l10n,
private IURLGenerator $urlGenerator,
private ReferenceManager $referenceManager,
Expand Down Expand Up @@ -85,7 +87,7 @@ public function matchReference(string $referenceText): bool {
return false;
}
}
$adminLinkPreviewEnabled = $this->config->getAppValue(Application::APP_ID, 'link_preview_enabled', '1') === '1';
$adminLinkPreviewEnabled = $this->appConfig->getAppValueString('link_preview_enabled', '1', lazy: true) === '1';
if (!$adminLinkPreviewEnabled) {
return false;
}
Expand Down
12 changes: 7 additions & 5 deletions lib/Service/GithubAPIService.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
use OCA\Github\AppInfo\Application;
use OCP\AppFramework\Services\IAppConfig;
use OCP\Dashboard\Model\WidgetItem;
use OCP\Http\Client\IClient;
use OCP\Http\Client\IClientService;
Expand All @@ -37,6 +38,7 @@ public function __construct(
private LoggerInterface $logger,
private IL10N $l10n,
private IConfig $config,
private IAppConfig $appConfig,
private IURLGenerator $urlGenerator,
private IUserManager $userManager,
private IManager $notificationManager,
Expand Down Expand Up @@ -377,15 +379,15 @@ public function getCommitInfo(?string $userId, string $owner, string $repo, stri
public function updateLinkTokenUserInfo(string $defaultLinkToken): array {
$info = $this->request(null, 'user', [], 'GET', true, 30, $defaultLinkToken);
if (isset($info['login'], $info['name'])) {
$this->config->setAppValue(Application::APP_ID, 'user_name', $info['login']);
$this->config->setAppValue(Application::APP_ID, 'user_displayname', $info['name']);
$this->appConfig->setAppValueString('user_name', $info['login'], lazy: true);
$this->appConfig->setAppValueString('user_displayname', $info['name'], lazy: true);
return [
'user_name' => $info['login'],
'user_displayname' => $info['name'],
];
} else {
$this->config->deleteAppValue(Application::APP_ID, 'user_name');
$this->config->deleteAppValue(Application::APP_ID, 'user_displayname');
$this->appConfig->deleteAppValue('user_name');
$this->appConfig->deleteAppValue('user_displayname');
return [
'user_name' => '',
'user_displayname' => '',
Expand All @@ -394,7 +396,7 @@ public function updateLinkTokenUserInfo(string $defaultLinkToken): array {
}

public function checkNewNotifications() {
$notificationEnabled = $this->config->getAppValue(Application::APP_ID, 'issue_notifications_enabled', '1') === '1';
$notificationEnabled = $this->appConfig->getAppValueString('issue_notifications_enabled', '1') === '1';
if (!$notificationEnabled) {
return;
}
Expand Down
Loading
Loading