diff --git a/composer.json b/composer.json index 2fe836a..ec652b1 100644 --- a/composer.json +++ b/composer.json @@ -50,5 +50,10 @@ "target-directory": "vendor-bin", "forward-command": true } + }, + "autoload": { + "psr-4": { + "OCA\\Gitlab\\": "lib/" + } } } diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index aea452d..d9e6257 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -17,25 +17,17 @@ use OCA\Gitlab\Search\GitlabSearchReposProvider; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; - use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\Collaboration\Reference\RenderReferenceEvent; -use OCP\IConfig; - use OCP\Util; class Application extends App implements IBootstrap { public const APP_ID = 'integration_gitlab'; public const DEFAULT_GITLAB_URL = 'https://gitlab.com'; - private IConfig $config; - public function __construct(array $urlParams = []) { parent::__construct(self::APP_ID, $urlParams); - - $container = $this->getContainer(); - $this->config = $container->get(IConfig::class); } public function register(IRegistrationContext $context): void { diff --git a/lib/Controller/ConfigController.php b/lib/Controller/ConfigController.php index ce82fac..4edd55f 100644 --- a/lib/Controller/ConfigController.php +++ b/lib/Controller/ConfigController.php @@ -13,7 +13,10 @@ use DateTime; use OCA\Gitlab\AppInfo\Application; +use OCA\Gitlab\Model\AdminConfig; +use OCA\Gitlab\Model\UserConfig; use OCA\Gitlab\Reference\GitlabReferenceProvider; +use OCA\Gitlab\Service\ConfigService; use OCA\Gitlab\Service\GitlabAPIService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; @@ -21,7 +24,6 @@ use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; -use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; use OCP\IURLGenerator; @@ -29,15 +31,17 @@ class ConfigController extends Controller { - public function __construct(string $appName, + public function __construct( + string $appName, IRequest $request, - private IConfig $config, + private ConfigService $config, private IURLGenerator $urlGenerator, private IL10N $l, private IInitialState $initialStateService, private GitlabAPIService $gitlabAPIService, private GitlabReferenceProvider $gitlabReferenceProvider, - private ?string $userId) { + private string $userId, + ) { parent::__construct($appName, $request); } @@ -48,14 +52,13 @@ public function __construct(string $appName, * @throws PreConditionNotMetException */ public function setConfig(array $values): DataResponse { - foreach ($values as $key => $value) { - if ($key === 'url' || $key === 'token') { - return new DataResponse([], Http::STATUS_BAD_REQUEST); - } - - $this->config->setUserValue($this->userId, Application::APP_ID, $key, $value); + $userConfig = UserConfig::fromArray($values); + if ($userConfig->url !== null || $userConfig->token !== null) { + return new DataResponse([], Http::STATUS_BAD_REQUEST); } + $userConfig->saveConfig($this->userId, $this->config); + return new DataResponse([]); } @@ -66,28 +69,27 @@ public function setConfig(array $values): DataResponse { * @throws PreConditionNotMetException */ public function setSensitiveConfig(array $values): DataResponse { + $userConfig = UserConfig::fromArray($values); + $userConfig->saveConfig($this->userId, $this->config); + // revoke the oauth token if needed - if (isset($values['token']) && $values['token'] === '') { - $tokenType = $this->config->getUserValue($this->userId, Application::APP_ID, 'token_type'); + if ($userConfig->token === '') { + $tokenType = $this->config->getUserTokenType($this->userId); if ($tokenType === 'oauth') { $this->gitlabAPIService->revokeOauthToken($this->userId); } } - foreach ($values as $key => $value) { - $this->config->setUserValue($this->userId, Application::APP_ID, $key, $value); - } - $result = []; - if (isset($values['token'])) { + if ($userConfig->token !== null) { // if the token is set, cleanup refresh token and expiration date - $this->config->deleteUserValue($this->userId, Application::APP_ID, 'token_type'); - $this->config->deleteUserValue($this->userId, Application::APP_ID, 'refresh_token'); - $this->config->deleteUserValue($this->userId, Application::APP_ID, 'token_expires_at'); + $this->config->deleteUserTokenType($this->userId); + $this->config->deleteUserRefreshToken($this->userId); + $this->config->deleteUserTokenExpiresAt($this->userId); $this->gitlabReferenceProvider->invalidateUserCache($this->userId); - if ($values['token'] && $values['token'] !== '') { + if ($userConfig->token !== '') { $info = $this->storeUserInfo(); if (isset($info['error'])) { return new DataResponse(['error' => $info['error']], Http::STATUS_BAD_REQUEST); @@ -96,13 +98,13 @@ public function setSensitiveConfig(array $values): DataResponse { $result['user_displayname'] = $info['userdisplayname'] ?? ''; // store token type if it's valid (so we have a user name) if ($result['user_name'] !== '') { - $this->config->setUserValue($this->userId, Application::APP_ID, 'token_type', 'personal'); + $this->config->setUserTokenType($this->userId, 'personal'); } } else { - $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, 'user_displayname'); - $this->config->deleteUserValue($this->userId, Application::APP_ID, 'token'); + $this->config->deleteUserId($this->userId); + $this->config->deleteUserName($this->userId); + $this->config->deleteUserDisplayName($this->userId); + $this->config->deleteUserToken($this->userId); $result['user_name'] = ''; } } @@ -116,13 +118,12 @@ public function setSensitiveConfig(array $values): DataResponse { * @return DataResponse */ public function setAdminConfig(array $values): DataResponse { - foreach ($values as $key => $value) { - if ($key === 'client_id' || $key === 'client_secret' || $key === 'oauth_instance_url') { - return new DataResponse([], Http::STATUS_BAD_REQUEST); - } - - $this->config->setAppValue(Application::APP_ID, $key, $value); + $adminConfig = AdminConfig::fromArray($values); + if ($adminConfig->client_id !== null || $adminConfig->client_secret !== null || $adminConfig->oauth_instance_url !== null) { + return new DataResponse([], Http::STATUS_BAD_REQUEST); } + + $adminConfig->saveConfig($this->config); return new DataResponse(1); } @@ -130,9 +131,9 @@ public function setAdminConfig(array $values): DataResponse { * @PasswordConfirmationRequired */ public function setSensitiveAdminConfig(array $values): DataResponse { - foreach ($values as $key => $value) { - $this->config->setAppValue(Application::APP_ID, $key, $value); - } + $adminConfig = AdminConfig::fromArray($values); + $adminConfig->saveConfig($this->config); + return new DataResponse(1); } @@ -160,21 +161,20 @@ public function popupSuccessPage(string $user_name, string $user_displayname): T * @throws PreConditionNotMetException */ public function oauthRedirect(string $code = '', string $state = ''): RedirectResponse { - $configState = $this->config->getUserValue($this->userId, Application::APP_ID, 'oauth_state'); - $clientID = $this->config->getAppValue(Application::APP_ID, 'client_id'); - $clientSecret = $this->config->getAppValue(Application::APP_ID, 'client_secret'); + $configState = $this->config->getUserOauthState($this->userId); + $clientID = $this->config->getAdminClientId(); + $clientSecret = $this->config->getAdminClientSecret(); // anyway, reset state - $this->config->deleteUserValue($this->userId, Application::APP_ID, 'oauth_state'); + $this->config->deleteUserOauthState($this->userId); if ($clientID and $clientSecret and $configState !== '' and $configState === $state) { - $redirect_uri = $this->config->getUserValue($this->userId, Application::APP_ID, 'redirect_uri'); - $adminOauthUrl = $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url', Application::DEFAULT_GITLAB_URL) ?: Application::DEFAULT_GITLAB_URL; + $adminOauthUrl = $this->config->getAdminOauthUrl(); $result = $this->gitlabAPIService->requestOAuthAccessToken($adminOauthUrl, [ 'client_id' => $clientID, 'client_secret' => $clientSecret, 'code' => $code, - 'redirect_uri' => $redirect_uri, + 'redirect_uri' => $this->config->getUserRedirectUri($this->userId), 'grant_type' => 'authorization_code' ], 'POST'); if (isset($result['access_token'])) { @@ -184,16 +184,15 @@ public function oauthRedirect(string $code = '', string $state = ''): RedirectRe 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', strval($expiresAt)); + $this->config->setUserTokenExpiresAt($this->userId, $expiresAt); } - $this->config->setUserValue($this->userId, Application::APP_ID, 'url', $adminOauthUrl); - $this->config->setUserValue($this->userId, Application::APP_ID, 'token', $accessToken); - $this->config->setUserValue($this->userId, Application::APP_ID, 'refresh_token', $refreshToken); - $this->config->setUserValue($this->userId, Application::APP_ID, 'token_type', 'oauth'); + $this->config->setUserUrl($this->userId, $adminOauthUrl); + $this->config->setUserToken($this->userId, $accessToken); + $this->config->setUserRefreshToken($this->userId, $refreshToken); + $this->config->setUserTokenType($this->userId, 'oauth'); $userInfo = $this->storeUserInfo(); - $usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0') === '1'; - if ($usePopup) { + if ($this->config->getAdminUsePopup()) { return new RedirectResponse( $this->urlGenerator->linkToRoute('integration_gitlab.config.popupSuccessPage', [ 'user_name' => $userInfo['username'] ?? '', @@ -201,8 +200,8 @@ public function oauthRedirect(string $code = '', string $state = ''): RedirectRe ]) ); } else { - $oauthOrigin = $this->config->getUserValue($this->userId, Application::APP_ID, 'oauth_origin'); - $this->config->deleteUserValue($this->userId, Application::APP_ID, 'oauth_origin'); + $oauthOrigin = $this->config->getUserOauthOrigin($this->userId); + $this->config->deleteUserOauthOrigin($this->userId); if ($oauthOrigin === 'settings') { return new RedirectResponse( $this->urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'connected-accounts']) . @@ -236,17 +235,17 @@ public function oauthRedirect(string $code = '', string $state = ''): RedirectRe private function storeUserInfo(): array { $info = $this->gitlabAPIService->request($this->userId, 'user'); if (isset($info['username']) && isset($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['username']); - $this->config->setUserValue($this->userId, Application::APP_ID, 'user_displayname', $info['name']); + $this->config->setUserId($this->userId, $info['id']); + $this->config->setUserName($this->userId, $info['username']); + $this->config->setUserDisplayName($this->userId, $info['name']); return [ 'username' => $info['username'], 'userid' => $info['id'], 'userdisplayname' => $info['name'], ]; } else { - $this->config->setUserValue($this->userId, Application::APP_ID, 'user_id', ''); - $this->config->setUserValue($this->userId, Application::APP_ID, 'user_name', ''); + $this->config->deleteUserId($this->userId); + $this->config->deleteUserName($this->userId); return $info; } } diff --git a/lib/Controller/GitlabAPIController.php b/lib/Controller/GitlabAPIController.php index f5aeeb2..ea8ba83 100644 --- a/lib/Controller/GitlabAPIController.php +++ b/lib/Controller/GitlabAPIController.php @@ -11,14 +11,13 @@ namespace OCA\Gitlab\Controller; -use OCA\Gitlab\AppInfo\Application; +use Exception; +use OCA\Gitlab\Service\ConfigService; use OCA\Gitlab\Service\GitlabAPIService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\DataDisplayResponse; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\RedirectResponse; - -use OCP\IConfig; use OCP\IRequest; use OCP\IURLGenerator; @@ -26,14 +25,16 @@ class GitlabAPIController extends Controller { private string $accessToken; - public function __construct(string $appName, - IRequest $request, - private IConfig $config, - private IURLGenerator $urlGenerator, + public function __construct( + string $appName, + IRequest $request, + private ConfigService $config, + private IURLGenerator $urlGenerator, private GitlabAPIService $gitlabAPIService, - private ?string $userId) { + private string $userId, + ) { parent::__construct($appName, $request); - $this->accessToken = $this->config->getUserValue($this->userId, Application::APP_ID, 'token'); + $this->accessToken = $this->config->getUserToken($userId); } /** @@ -43,7 +44,7 @@ public function __construct(string $appName, * * @param int $userId * @return DataDisplayResponse|RedirectResponse - * @throws \Exception + * @throws Exception */ public function getUserAvatar(int $userId) { $result = $this->gitlabAPIService->getUserAvatar($this->userId, $userId); @@ -65,7 +66,7 @@ public function getUserAvatar(int $userId) { * * @param int $projectId * @return DataDisplayResponse|RedirectResponse - * @throws \Exception + * @throws Exception */ public function getProjectAvatar(int $projectId) { $result = $this->gitlabAPIService->getProjectAvatar($this->userId, $projectId); @@ -86,7 +87,7 @@ public function getProjectAvatar(int $projectId) { * * @param string|null $since * @return DataResponse - * @throws \Exception + * @throws Exception */ public function getEvents(?string $since = null): DataResponse { if ($this->accessToken === '') { @@ -107,7 +108,7 @@ public function getEvents(?string $since = null): DataResponse { * * @param string|null $since * @return DataResponse - * @throws \Exception + * @throws Exception */ public function getTodos(?string $since = null): DataResponse { if ($this->accessToken === '') { @@ -127,7 +128,7 @@ public function getTodos(?string $since = null): DataResponse { * * @param int $id * @return DataResponse - * @throws \Exception + * @throws Exception */ public function markTodoAsDone(int $id): DataResponse { if ($this->accessToken === '') { diff --git a/lib/Dashboard/GitlabWidget.php b/lib/Dashboard/GitlabWidget.php index ee4393a..7c43a10 100644 --- a/lib/Dashboard/GitlabWidget.php +++ b/lib/Dashboard/GitlabWidget.php @@ -24,21 +24,22 @@ namespace OCA\Gitlab\Dashboard; use OCA\Gitlab\AppInfo\Application; +use OCA\Gitlab\Service\ConfigService; use OCP\AppFramework\Services\IInitialState; use OCP\Dashboard\IWidget; -use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; - use OCP\Util; class GitlabWidget implements IWidget { - public function __construct(private IL10N $l10n, - private IConfig $config, + public function __construct( + private IL10N $l10n, + private ConfigService $config, private IURLGenerator $url, private IInitialState $initialStateService, - private ?string $userId) { + private string $userId, + ) { } /** @@ -80,16 +81,15 @@ 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'); - $adminOauthUrl = $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url', Application::DEFAULT_GITLAB_URL) ?: Application::DEFAULT_GITLAB_URL; - $url = $this->config->getUserValue($this->userId, Application::APP_ID, 'url', $adminOauthUrl) ?: $adminOauthUrl; - $oauthPossible = $clientID !== '' && $clientSecret !== '' && $url === $adminOauthUrl; - $usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0'); + $clientID = $this->config->getAdminClientId(); + $clientSecret = $this->config->getAdminClientSecret(); + $adminOauthUrl = $this->config->getAdminOauthUrl(); + $url = $this->config->getUserUrl($this->userId); + $usePopup = $this->config->getAdminUsePopup(); $userConfig = [ - 'oauth_is_possible' => $oauthPossible, - 'use_popup' => ($usePopup === '1'), + 'oauth_is_possible' => $clientID !== '' && $clientSecret !== '' && $url === $adminOauthUrl, + 'use_popup' => $usePopup, 'url' => $url, 'client_id' => $clientID, ]; diff --git a/lib/Model/AdminConfig.php b/lib/Model/AdminConfig.php new file mode 100644 index 0000000..03dbc8e --- /dev/null +++ b/lib/Model/AdminConfig.php @@ -0,0 +1,66 @@ +getAdminClientId(), + client_secret: $config->getAdminClientSecret(), + oauth_instance_url: $config->getAdminOauthUrl(), + use_popup: $config->getAdminUsePopup(), + link_preview_enabled: $config->getAdminLinkPreviewEnabled(), + ); + } + + public function saveConfig(ConfigService $config): void { + if ($this->client_id !== null) { + $config->setAdminClientId($this->client_id); + } + if ($this->client_secret !== null) { + $config->setAdminClientSecret($this->client_secret); + } + if ($this->oauth_instance_url !== null) { + $config->setAdminOauthUrl($this->oauth_instance_url); + } + if ($this->use_popup !== null) { + $config->setAdminUsePopup($this->use_popup); + } + if ($this->link_preview_enabled !== null) { + $config->setAdminLinkPreviewEnabled($this->link_preview_enabled); + } + } + + public static function fromArray(array $config): AdminConfig { + return new AdminConfig( + client_id: $config['client_id'] ?? null, + client_secret: $config['client_secret'] ?? null, + oauth_instance_url: $config['oauth_instance_url'] ?? null, + use_popup: $config['use_popup'] ?? null, + link_preview_enabled: $config['link_preview_enabled'] ?? null, + ); + } + + public function toArray(): array { + return [ + 'client_id' => $this->client_id, + 'client_secret' => $this->client_secret !== null && $this->client_secret !== '' ? 'dummyToken' : $this->client_secret, + 'oauth_instance_url' => $this->oauth_instance_url, + 'use_popup' => $this->use_popup, + 'link_preview_enabled' => $this->link_preview_enabled, + ]; + } +} diff --git a/lib/Model/UserConfig.php b/lib/Model/UserConfig.php new file mode 100644 index 0000000..22f1725 --- /dev/null +++ b/lib/Model/UserConfig.php @@ -0,0 +1,134 @@ +getUserToken($userId), + url: $config->getUserUrl($userId), + client_id: $config->getAdminClientId(), + client_secret: $config->hasAdminClientSecret(), + oauth_instance_url: $config->getAdminOauthUrl(), + use_popup: $config->getAdminUsePopup(), + user_name: $config->getUserName($userId), + user_displayname: $config->getUserDisplayName($userId), + search_enabled: $config->getUserSearchEnabled($userId), + search_issues_enabled: $config->getUserSearchIssuesEnabled($userId), + search_mrs_enabled: $config->getUserSearchMergeRequestsEnabled($userId), + navigation_enabled: $config->getUserNavigationEnabled($userId), + link_preview_enabled: $config->getUserLinkPreviewEnabled($userId), + oauth_state: $config->getUserOauthState($userId), + redirect_uri: $config->getUserRedirectUri($userId), + oauth_origin: $config->getUserOauthOrigin($userId), + ); + } + + /** + * @throws PreConditionNotMetException|InvalidArgumentException + */ + public function saveConfig(string $userId, ConfigService $config): void { + if ($this->client_id !== null || $this->client_secret !== null || $this->oauth_instance_url !== null || $this->use_popup !== null || $this->user_name !== null || $this->user_displayname !== null) { + throw new InvalidArgumentException(); + } + if ($this->token !== null) { + $config->setUserToken($userId, $this->token); + } + if ($this->url !== null) { + $config->setUserUrl($userId, $this->url); + } + if ($this->search_enabled !== null) { + $config->setUserSearchEnabled($userId, $this->search_enabled); + } + if ($this->search_issues_enabled !== null) { + $config->setUserSearchIssuesEnabled($userId, $this->search_issues_enabled); + } + if ($this->search_mrs_enabled !== null) { + $config->setUserSearchMergeRequestsEnabled($userId, $this->search_mrs_enabled); + } + if ($this->navigation_enabled !== null) { + $config->setUserNavigationEnabled($userId, $this->navigation_enabled); + } + if ($this->link_preview_enabled !== null) { + $config->setUserLinkPreviewEnabled($userId, $this->link_preview_enabled); + } + if ($this->oauth_state !== null) { + $config->setUserOauthState($userId, $this->oauth_state); + } + if ($this->redirect_uri !== null) { + $config->setUserRedirectUri($userId, $this->redirect_uri); + } + if ($this->oauth_origin !== null) { + $config->setUserOauthOrigin($userId, $this->oauth_origin); + } + } + + public static function fromArray(array $config): UserConfig { + return new UserConfig( + token: $config['token'] ?? null, + url: $config['url'] ?? null, + client_id: $config['client_id'] ?? null, + client_secret: $config['client_secret'] ?? null, + oauth_instance_url: $config['oauth_instance_url'] ?? null, + use_popup: $config['use_popup'] ?? null, + user_name: $config['user_name'] ?? null, + user_displayname: $config['user_displayname'] ?? null, + search_enabled: $config['search_enabled'] ?? null, + search_issues_enabled: $config['search_issues_enabled'] ?? null, + search_mrs_enabled: $config['search_mrs_enabled'] ?? null, + navigation_enabled: $config['navigation_enabled'] ?? null, + link_preview_enabled: $config['link_preview_enabled'] ?? null, + oauth_state: $config['oauth_state'] ?? null, + redirect_uri: $config['redirect_uri'] ?? null, + oauth_origin: $config['oauth_origin'] ?? null, + ); + } + + public function toArray(): array { + return [ + 'token' => $this->token !== null && $this->token !== '' ? 'dummyToken' : $this->token, + 'url' => $this->url, + 'client_id' => $this->client_id, + 'client_secret' => $this->client_secret, + 'oauth_instance_url' => $this->oauth_instance_url, + 'use_popup' => $this->use_popup, + 'user_name' => $this->user_name, + 'user_displayname' => $this->user_displayname, + 'search_enabled' => $this->search_enabled, + 'search_issues_enabled' => $this->search_issues_enabled, + 'search_mrs_enabled' => $this->search_mrs_enabled, + 'navigation_enabled' => $this->navigation_enabled, + 'link_preview_enabled' => $this->link_preview_enabled, + 'oauth_state' => $this->oauth_state, + 'redirect_uri' => $this->redirect_uri, + 'oauth_origin' => $this->oauth_origin, + ]; + } +} diff --git a/lib/Reference/GitlabReferenceProvider.php b/lib/Reference/GitlabReferenceProvider.php index 3c1a6ed..6670fb7 100644 --- a/lib/Reference/GitlabReferenceProvider.php +++ b/lib/Reference/GitlabReferenceProvider.php @@ -26,12 +26,12 @@ use Exception; use OC\Collaboration\Reference\ReferenceManager; use OCA\Gitlab\AppInfo\Application; +use OCA\Gitlab\Service\ConfigService; use OCA\Gitlab\Service\GitlabAPIService; use OCP\Collaboration\Reference\ADiscoverableReferenceProvider; use OCP\Collaboration\Reference\IReference; use OCP\Collaboration\Reference\ISearchableReferenceProvider; use OCP\Collaboration\Reference\Reference; -use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; use OCP\PreConditionNotMetException; @@ -39,12 +39,14 @@ class GitlabReferenceProvider extends ADiscoverableReferenceProvider implements ISearchableReferenceProvider { - public function __construct(private GitlabAPIService $gitlabAPIService, - private IConfig $config, + public function __construct( + private GitlabAPIService $gitlabAPIService, + private ConfigService $config, private ReferenceManager $referenceManager, private IURLGenerator $urlGenerator, private IL10N $l10n, - private ?string $userId) { + private ?string $userId, + ) { } /** @@ -92,11 +94,10 @@ private function getGitlabUrls(): array { // return ['https://gitlab.com']; //} $urls = []; - $adminOauthUrl = $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url', Application::DEFAULT_GITLAB_URL) ?: Application::DEFAULT_GITLAB_URL; if ($this->userId !== null) { - $urls[] = $this->config->getUserValue($this->userId, Application::APP_ID, 'url', $adminOauthUrl) ?: $adminOauthUrl; + $urls[] = $this->config->getUserUrl($this->userId); } else { - $urls[] = $adminOauthUrl; + $urls[] = $this->config->getAdminOauthUrl(); } // unfortunately most of what we need for reference stuff requires authentication // let's not allow to handle multiple gitlab servers @@ -132,12 +133,12 @@ private function getMatchingGitlabUrl($referenceText): ?string { */ public function matchReference(string $referenceText): bool { if ($this->userId !== null) { - $linkPreviewEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'link_preview_enabled', '1') === '1'; + $linkPreviewEnabled = $this->config->getUserLinkPreviewEnabled($this->userId); if (!$linkPreviewEnabled) { return false; } } - $adminLinkPreviewEnabled = $this->config->getAppValue(Application::APP_ID, 'link_preview_enabled', '1') === '1'; + $adminLinkPreviewEnabled = $this->config->getAdminLinkPreviewEnabled(); if (!$adminLinkPreviewEnabled) { return false; } @@ -225,14 +226,14 @@ private function getGenericCommentInfo(array $commentInfo): array { try { $ts = (new DateTime($commentInfo['created_at']))->getTimestamp(); $info['created_at'] = $ts; - } catch (Exception | Throwable $e) { + } catch (Exception|Throwable $e) { } } if (isset($commentInfo['updated_at'])) { try { $ts = (new DateTime($commentInfo['updated_at']))->getTimestamp(); $info['updated_at'] = $ts; - } catch (Exception | Throwable $e) { + } catch (Exception|Throwable $e) { } } if (isset($commentInfo['author'], $commentInfo['author']['username'])) { @@ -272,7 +273,7 @@ private function getGenericIssueInfo(array $issueInfo, array $projectLabels): ar try { $ts = (new DateTime($issueInfo['created_at']))->getTimestamp(); $info['created_at'] = $ts; - } catch (Exception | Throwable $e) { + } catch (Exception|Throwable $e) { } } if (isset($issueInfo['author'], $issueInfo['author']['username'])) { @@ -312,7 +313,7 @@ private function getGenericPrInfo(array $prInfo, array $projectLabels): array { try { $ts = (new DateTime($prInfo['created_at']))->getTimestamp(); $info['created_at'] = $ts; - } catch (Exception | Throwable $e) { + } catch (Exception|Throwable $e) { } } if (isset($prInfo['author'], $prInfo['author']['username'])) { @@ -338,7 +339,7 @@ private function getIssuePath(string $gitlabUrl, string $url): ?array { * @return array|null */ private function getPrPath(string $gitlabUrl, string $url): ?array { - preg_match('/^'. preg_quote($gitlabUrl, '/') . '\/([^\/\?]+)\/([^\/\?]+)\/-\/merge_requests\/([0-9]+)(.*$)/', $url, $matches); + preg_match('/^' . preg_quote($gitlabUrl, '/') . '\/([^\/\?]+)\/([^\/\?]+)\/-\/merge_requests\/([0-9]+)(.*$)/', $url, $matches); return count($matches) > 3 ? [$matches[1], $matches[2], $matches[3], $matches[4]] : null; } @@ -348,7 +349,7 @@ private function getPrPath(string $gitlabUrl, string $url): ?array { */ private function getCommentId(string $urlEnd): ?int { preg_match('/^#note_([0-9]+)$/', $urlEnd, $matches); - return (count($matches) > 1) ? ((int) $matches[1]) : null; + return (count($matches) > 1) ? ((int)$matches[1]) : null; } /** diff --git a/lib/Search/GitlabSearchIssuesProvider.php b/lib/Search/GitlabSearchIssuesProvider.php index 4b9eb2e..662508c 100644 --- a/lib/Search/GitlabSearchIssuesProvider.php +++ b/lib/Search/GitlabSearchIssuesProvider.php @@ -22,12 +22,13 @@ * along with this program. If not, see * */ + namespace OCA\Gitlab\Search; use OCA\Gitlab\AppInfo\Application; +use OCA\Gitlab\Service\ConfigService; use OCA\Gitlab\Service\GitlabAPIService; use OCP\App\IAppManager; -use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUser; @@ -38,11 +39,13 @@ class GitlabSearchIssuesProvider implements IProvider { - public function __construct(private IAppManager $appManager, - private IL10N $l10n, - private IConfig $config, - private IURLGenerator $urlGenerator, - private GitlabAPIService $service) { + public function __construct( + private IAppManager $appManager, + private IL10N $l10n, + private ConfigService $config, + private IURLGenerator $urlGenerator, + private GitlabAPIService $service, + ) { } /** @@ -87,18 +90,17 @@ public function search(IUser $user, ISearchQuery $query): SearchResult { $routeFrom = $query->getRoute(); $requestedFromSmartPicker = $routeFrom === '' || $routeFrom === 'smart-picker'; - $searchIssuesEnabled = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'search_issues_enabled', '0') === '1'; + $searchIssuesEnabled = $this->config->getUserSearchIssuesEnabled($user->getUID()); if (!$requestedFromSmartPicker && !$searchIssuesEnabled) { return SearchResult::paginated($this->getName(), [], 0); } - $accessToken = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'token'); + $accessToken = $this->config->getUserToken($user->getUID()); if ($accessToken === '') { return SearchResult::paginated($this->getName(), [], 0); } - $adminOauthUrl = $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url', Application::DEFAULT_GITLAB_URL) ?: Application::DEFAULT_GITLAB_URL; - $url = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'url', $adminOauthUrl) ?: $adminOauthUrl; + $url = $this->config->getUserUrl($user->getUID()); $issues = $this->service->searchIssues($user->getUID(), $term, $offset, $limit); if (isset($issues['error'])) { diff --git a/lib/Search/GitlabSearchMergeRequestsProvider.php b/lib/Search/GitlabSearchMergeRequestsProvider.php index 960a7bb..7e0f3db 100644 --- a/lib/Search/GitlabSearchMergeRequestsProvider.php +++ b/lib/Search/GitlabSearchMergeRequestsProvider.php @@ -22,12 +22,13 @@ * along with this program. If not, see * */ + namespace OCA\Gitlab\Search; use OCA\Gitlab\AppInfo\Application; +use OCA\Gitlab\Service\ConfigService; use OCA\Gitlab\Service\GitlabAPIService; use OCP\App\IAppManager; -use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUser; @@ -38,11 +39,13 @@ class GitlabSearchMergeRequestsProvider implements IProvider { - public function __construct(private IAppManager $appManager, - private IL10N $l10n, - private IConfig $config, - private IURLGenerator $urlGenerator, - private GitlabAPIService $service) { + public function __construct( + private IAppManager $appManager, + private IL10N $l10n, + private ConfigService $config, + private IURLGenerator $urlGenerator, + private GitlabAPIService $service, + ) { } /** @@ -87,18 +90,17 @@ public function search(IUser $user, ISearchQuery $query): SearchResult { $routeFrom = $query->getRoute(); $requestedFromSmartPicker = $routeFrom === '' || $routeFrom === 'smart-picker'; - $searchMRsEnabled = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'search_mrs_enabled', '0') === '1'; + $searchMRsEnabled = $this->config->getUserSearchMergeRequestsEnabled($user->getUID()); if (!$requestedFromSmartPicker && !$searchMRsEnabled) { return SearchResult::paginated($this->getName(), [], 0); } - $accessToken = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'token'); + $accessToken = $this->config->getUserToken($user->getUID()); if ($accessToken === '') { return SearchResult::paginated($this->getName(), [], 0); } - $adminOauthUrl = $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url', Application::DEFAULT_GITLAB_URL) ?: Application::DEFAULT_GITLAB_URL; - $url = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'url', $adminOauthUrl) ?: $adminOauthUrl; + $url = $this->config->getUserUrl($user->getUID()); $mergeRequests = $this->service->searchMergeRequests($user->getUID(), $term, $offset, $limit); if (isset($mergeRequests['error'])) { @@ -152,7 +154,7 @@ protected function getSubline(array $entry, string $url): string { $number = $entry['iid']; $typeChar = '⑃'; $idChar = '!'; - return $typeChar . ' '. $idChar . $number . ' ' . $repoFullName; + return $typeChar . ' ' . $idChar . $number . ' ' . $repoFullName; } /** diff --git a/lib/Search/GitlabSearchReposProvider.php b/lib/Search/GitlabSearchReposProvider.php index 9ab68b7..4098f64 100644 --- a/lib/Search/GitlabSearchReposProvider.php +++ b/lib/Search/GitlabSearchReposProvider.php @@ -22,12 +22,13 @@ * along with this program. If not, see * */ + namespace OCA\Gitlab\Search; use OCA\Gitlab\AppInfo\Application; +use OCA\Gitlab\Service\ConfigService; use OCA\Gitlab\Service\GitlabAPIService; use OCP\App\IAppManager; -use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUser; @@ -38,11 +39,13 @@ class GitlabSearchReposProvider implements IProvider { - public function __construct(private IAppManager $appManager, + public function __construct( + private IAppManager $appManager, private IL10N $l10n, - private IConfig $config, + private ConfigService $config, private IURLGenerator $urlGenerator, - private GitlabAPIService $service) { + private GitlabAPIService $service, + ) { } /** @@ -87,12 +90,12 @@ public function search(IUser $user, ISearchQuery $query): SearchResult { $routeFrom = $query->getRoute(); $requestedFromSmartPicker = $routeFrom === '' || $routeFrom === 'smart-picker'; - $searchEnabled = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'search_enabled', '0') === '1'; + $searchEnabled = $this->config->getUserSearchEnabled($user->getUID()); if (!$requestedFromSmartPicker && !$searchEnabled) { return SearchResult::paginated($this->getName(), [], 0); } - $accessToken = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'token'); + $accessToken = $this->config->getUserToken($user->getUID()); if ($accessToken === '') { return SearchResult::paginated($this->getName(), [], 0); } diff --git a/lib/Service/ConfigService.php b/lib/Service/ConfigService.php new file mode 100644 index 0000000..0cce786 --- /dev/null +++ b/lib/Service/ConfigService.php @@ -0,0 +1,276 @@ +config->getAppValue(Application::APP_ID, 'client_id'); + } + + public function setAdminClientId(string $clientId): void { + $this->config->setAppValue(Application::APP_ID, 'client_id', $clientId); + } + + public function hasAdminClientSecret(): bool { + return $this->getAdminClientSecret() !== ''; + } + + public function getAdminClientSecret(): string { + return $this->config->getAppValue(Application::APP_ID, 'client_secret'); + } + + public function setAdminClientSecret(string $clientSecret): void { + $this->config->setAppValue(Application::APP_ID, 'client_secret', $clientSecret); + } + + public function getAdminOauthUrl(): string { + return $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url') ?: Application::DEFAULT_GITLAB_URL; + } + + public function setAdminOauthUrl(string $url): void { + $this->config->setAppValue(Application::APP_ID, 'oauth_instance_url', $url); + } + + public function getAdminUsePopup(): bool { + return $this->config->getAppValue(Application::APP_ID, 'use_popup', '0') === '1'; + } + + public function setAdminUsePopup(bool $enabled): void { + $this->config->setAppValue(Application::APP_ID, 'use_popup', $enabled ? '1' : '0'); + } + + public function getAdminLinkPreviewEnabled(): bool { + return $this->config->getAppValue(Application::APP_ID, 'link_preview_enabled', '1') === '1'; + } + + public function setAdminLinkPreviewEnabled(bool $enabled): void { + $this->config->setAppValue(Application::APP_ID, 'link_preview_enabled', $enabled ? '1' : '0'); + } + + public function getUserUrl(string $userId): string { + return $this->config->getUserValue($userId, Application::APP_ID, 'url') ?: $this->getAdminOauthUrl(); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserUrl(string $userId, string $url): void { + $this->config->setUserValue($userId, Application::APP_ID, 'url', $url); + } + + public function getUserTokenType(string $userId): string { + return $this->config->getUserValue($userId, Application::APP_ID, 'token_type'); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserTokenType(string $userId, string $type): void { + $this->config->setUserValue($userId, Application::APP_ID, 'token_type', $type); + } + + public function deleteUserTokenType(string $userId): void { + $this->config->deleteUserValue($userId, Application::APP_ID, 'token_type'); + } + + public function hasUserRefreshToken(string $userId): bool { + return $this->config->getUserValue($userId, Application::APP_ID, 'refresh_token') !== ''; + } + + public function getUserRefreshToken(string $userId): string { + return $this->config->getUserValue($userId, Application::APP_ID, 'refresh_token'); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserRefreshToken(string $userId, string $refreshToken): void { + $this->config->setUserValue($userId, Application::APP_ID, 'refresh_token', $refreshToken); + } + + public function deleteUserRefreshToken(string $userId): void { + $this->config->deleteUserValue($userId, Application::APP_ID, 'refresh_token'); + } + + public function hasUserTokenExpiresAt(string $userId): bool { + return $this->config->getUserValue($userId, Application::APP_ID, 'token_expires_at') !== ''; + } + + public function getUserTokenExpiresAt(string $userId): int { + return (int)$this->config->getUserValue($userId, Application::APP_ID, 'token_expires_at'); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserTokenExpiresAt(string $userId, int $expiresAt): void { + $this->config->setUserValue($userId, Application::APP_ID, 'token_expires_at', (string)$expiresAt); + } + + public function deleteUserTokenExpiresAt(string $userId): void { + $this->config->deleteUserValue($userId, Application::APP_ID, 'token_expires_at'); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserId(string $userId, string $id): void { + $this->config->setUserValue($userId, Application::APP_ID, 'user_id', $id); + } + + public function deleteUserId(string $userId): void { + $this->config->deleteUserValue($userId, Application::APP_ID, 'user_id'); + } + + public function getUserName(string $userId): string { + return $this->config->getUserValue($userId, Application::APP_ID, 'user_name'); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserName(string $userId, string $name): void { + $this->config->setUserValue($userId, Application::APP_ID, 'user_name', $name); + } + + public function deleteUserName(string $userId): void { + $this->config->deleteUserValue($userId, Application::APP_ID, 'user_name'); + } + + public function getUserDisplayName(string $userId): string { + return $this->config->getUserValue($userId, Application::APP_ID, 'user_displayname'); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserDisplayName(string $userId, string $displayName): void { + $this->config->setUserValue($userId, Application::APP_ID, 'user_displayname', $displayName); + } + + public function deleteUserDisplayName(string $userId): void { + $this->config->deleteUserValue($userId, Application::APP_ID, 'user_displayname'); + } + + public function getUserToken(string $userId): string { + return $this->config->getUserValue($userId, Application::APP_ID, 'token'); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserToken(string $userId, string $token): void { + $this->config->setUserValue($userId, Application::APP_ID, 'token', $token); + } + + public function deleteUserToken(string $userId): void { + $this->config->deleteUserValue($userId, Application::APP_ID, 'token'); + } + + public function getUserOauthState(string $userId): string { + return $this->config->getUserValue($userId, Application::APP_ID, 'oauth_state'); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserOauthState(string $userId, string $state): void { + $this->config->setUserValue($userId, Application::APP_ID, 'oauth_state', $state); + } + + public function deleteUserOauthState(string $userId): void { + $this->config->deleteUserValue($userId, Application::APP_ID, 'oauth_state'); + } + + public function getUserRedirectUri(string $userId): string { + return $this->config->getUserValue($userId, Application::APP_ID, 'redirect_uri'); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserRedirectUri(string $userId, string $redirectUri): void { + $this->config->setUserValue($userId, Application::APP_ID, 'redirect_uri', $redirectUri); + } + + public function getUserOauthOrigin(string $userId): string { + return $this->config->getUserValue($userId, Application::APP_ID, 'oauth_origin'); + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserOauthOrigin(string $userId, string $origin): void { + $this->config->setUserValue($userId, Application::APP_ID, 'oauth_origin', $origin); + } + + public function deleteUserOauthOrigin(string $userId): void { + $this->config->deleteUserValue($userId, Application::APP_ID, 'oauth_origin'); + } + + public function getUserSearchEnabled(string $userId): bool { + return $this->config->getUserValue($userId, Application::APP_ID, 'search_enabled', '0') === '1'; + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserSearchEnabled(string $userId, bool $enabled): void { + $this->config->setUserValue($userId, Application::APP_ID, 'search_enabled', $enabled ? '1' : '0'); + } + + public function getUserSearchIssuesEnabled(string $userId): bool { + return $this->config->getUserValue($userId, Application::APP_ID, 'search_issues_enabled', '0') === '1'; + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserSearchIssuesEnabled(string $userId, bool $enabled): void { + $this->config->setUserValue($userId, Application::APP_ID, 'search_issues_enabled', $enabled ? '1' : '0'); + } + + public function getUserSearchMergeRequestsEnabled(string $userId): bool { + return $this->config->getUserValue($userId, Application::APP_ID, 'search_mrs_enabled', '0') === '1'; + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserSearchMergeRequestsEnabled(string $userId, bool $enabled): void { + $this->config->setUserValue($userId, Application::APP_ID, 'search_mrs_enabled', $enabled ? '1' : '0'); + } + + public function getUserNavigationEnabled(string $userId): bool { + return $this->config->getUserValue($userId, Application::APP_ID, 'navigation_enabled', '0') === '1'; + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserNavigationEnabled(string $userId, bool $enabled): void { + $this->config->setUserValue($userId, Application::APP_ID, 'navigation_enabled', $enabled ? '1' : '0'); + } + + public function getUserLinkPreviewEnabled(string $userId): bool { + return $this->config->getUserValue($userId, Application::APP_ID, 'link_preview_enabled', '1') === '1'; + } + + /** + * @throws PreConditionNotMetException + */ + public function setUserLinkPreviewEnabled(string $userId, bool $enabled): void { + $this->config->setUserValue($userId, Application::APP_ID, 'link_preview_enabled', $enabled ? '1' : '0'); + } +} diff --git a/lib/Service/GitlabAPIService.php b/lib/Service/GitlabAPIService.php index 2ccae0b..76c1a00 100644 --- a/lib/Service/GitlabAPIService.php +++ b/lib/Service/GitlabAPIService.php @@ -21,7 +21,6 @@ use OCA\Gitlab\AppInfo\Application; use OCP\Http\Client\IClient; use OCP\Http\Client\IClientService; -use OCP\IConfig; use OCP\IL10N; use OCP\PreConditionNotMetException; use Psr\Log\LoggerInterface; @@ -33,11 +32,12 @@ class GitlabAPIService { private IClient $client; - public function __construct(string $appName, + public function __construct( private LoggerInterface $logger, - private IL10N $l10n, - private IConfig $config, - IClientService $clientService) { + private IL10N $l10n, + private ConfigService $config, + IClientService $clientService, + ) { $this->client = $clientService->newClient(); } @@ -448,11 +448,10 @@ public function request(?string $userId, string $endPoint, array $params = [], s if ($userId !== null) { $this->checkTokenExpiration($userId); } - $adminOauthUrl = $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url', Application::DEFAULT_GITLAB_URL) ?: Application::DEFAULT_GITLAB_URL; if ($userId === null) { - $baseUrl = $adminOauthUrl; + $baseUrl = $this->config->getAdminOauthUrl(); } else { - $baseUrl = $this->config->getUserValue($userId, Application::APP_ID, 'url', $adminOauthUrl) ?: $adminOauthUrl; + $baseUrl = $this->config->getUserUrl($userId); } try { $url = $baseUrl . '/api/v4/' . $endPoint; @@ -464,7 +463,7 @@ public function request(?string $userId, string $endPoint, array $params = [], s // try anonymous request if no user (public page) or user not connected to a gitlab account if ($userId !== null) { - $accessToken = $this->config->getUserValue($userId, Application::APP_ID, 'token'); + $accessToken = $this->config->getUserToken($userId); if ($accessToken !== '') { $options['headers']['Authorization'] = 'Bearer ' . $accessToken; } @@ -524,13 +523,10 @@ public function request(?string $userId, string $endPoint, array $params = [], s * @throws PreConditionNotMetException */ private function checkTokenExpiration(string $userId): void { - $refreshToken = $this->config->getUserValue($userId, Application::APP_ID, 'refresh_token'); - $expireAt = $this->config->getUserValue($userId, Application::APP_ID, 'token_expires_at'); - if ($refreshToken !== '' && $expireAt !== '') { + if ($this->config->hasUserRefreshToken($userId) && $this->config->hasUserTokenExpiresAt($userId)) { $nowTs = (new DateTime())->getTimestamp(); - $expireAt = (int) $expireAt; // if token expires in less than a minute or is already expired - if ($nowTs > $expireAt - 60) { + if ($nowTs > $this->config->getUserTokenExpiresAt($userId) - 60) { $this->refreshToken($userId); } } @@ -542,33 +538,30 @@ private function checkTokenExpiration(string $userId): void { * @throws PreConditionNotMetException */ private function refreshToken(string $userId): bool { - $adminOauthUrl = $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url', Application::DEFAULT_GITLAB_URL) ?: Application::DEFAULT_GITLAB_URL; - $clientID = $this->config->getAppValue(Application::APP_ID, 'client_id'); - $clientSecret = $this->config->getAppValue(Application::APP_ID, 'client_secret'); - $redirect_uri = $this->config->getUserValue($userId, Application::APP_ID, 'redirect_uri'); - $refreshToken = $this->config->getUserValue($userId, Application::APP_ID, 'refresh_token'); + $adminOauthUrl = $this->config->getAdminOauthUrl(); + $refreshToken = $this->config->getUserRefreshToken($userId); if (!$refreshToken) { $this->logger->error('No GitLab refresh token found', ['app' => Application::APP_ID]); return false; } $result = $this->requestOAuthAccessToken($adminOauthUrl, [ - 'client_id' => $clientID, - 'client_secret' => $clientSecret, + 'client_id' => $this->config->getAdminClientId(), + 'client_secret' => $this->config->getAdminClientSecret(), 'grant_type' => 'refresh_token', - 'redirect_uri' => $redirect_uri, + 'redirect_uri' => $this->config->getUserRedirectUri($userId), 'refresh_token' => $refreshToken, ], 'POST'); if (isset($result['access_token'])) { $this->logger->info('GitLab access token successfully refreshed', ['app' => Application::APP_ID]); $accessToken = $result['access_token']; $refreshToken = $result['refresh_token']; - $this->config->setUserValue($userId, Application::APP_ID, 'url', $adminOauthUrl); - $this->config->setUserValue($userId, Application::APP_ID, 'token', $accessToken); - $this->config->setUserValue($userId, Application::APP_ID, 'refresh_token', $refreshToken); + $this->config->setUserUrl($userId, $adminOauthUrl); + $this->config->setUserToken($userId, $accessToken); + $this->config->setUserRefreshToken($userId, $refreshToken); 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', strval($expiresAt)); + $this->config->setUserTokenExpiresAt($userId, $expiresAt); } return true; } else { @@ -588,23 +581,17 @@ private function refreshToken(string $userId): bool { * @return array */ public function revokeOauthToken(string $userId): array { - $adminOauthUrl = $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url', Application::DEFAULT_GITLAB_URL) ?: Application::DEFAULT_GITLAB_URL; - - $accessToken = $this->config->getUserValue($userId, Application::APP_ID, 'token'); - $clientId = $this->config->getAppValue(Application::APP_ID, 'client_id'); - $clientSecret = $this->config->getAppValue(Application::APP_ID, 'client_secret'); - $endPoint = 'oauth/revoke'; try { - $url = $adminOauthUrl . '/' . $endPoint; + $url = $this->config->getAdminOauthUrl() . '/oauth/revoke'; $options = [ 'headers' => [ 'User-Agent' => 'Nextcloud GitLab integration', 'Content-Type' => 'application/json', ], 'body' => json_encode([ - 'client_id' => $clientId, - 'client_secret' => $clientSecret, - 'token' => $accessToken, + 'client_id' => $this->config->getAdminClientId(), + 'client_secret' => $this->config->getAdminClientSecret(), + 'token' => $this->config->getUserToken($userId), ]), ]; diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index 0aa6f9e..d643924 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -3,36 +3,25 @@ namespace OCA\Gitlab\Settings; use OCA\Gitlab\AppInfo\Application; +use OCA\Gitlab\Model\AdminConfig; +use OCA\Gitlab\Service\ConfigService; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; -use OCP\IConfig; use OCP\Settings\ISettings; class Admin implements ISettings { - public function __construct(private IConfig $config, - private IInitialState $initialStateService) { + public function __construct( + private ConfigService $config, + private IInitialState $initialStateService, + ) { } /** * @return TemplateResponse */ public function getForm(): TemplateResponse { - $clientID = $this->config->getAppValue(Application::APP_ID, 'client_id'); - // Do not expose the saved client secret to the user - $clientSecret = $this->config->getAppValue(Application::APP_ID, 'client_secret') !== '' ? 'dummyToken' : ''; - $oauthUrl = $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url'); - $usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0') === '1'; - $adminLinkPreviewEnabled = $this->config->getAppValue(Application::APP_ID, 'link_preview_enabled', '1') === '1'; - - $adminConfig = [ - 'client_id' => $clientID, - 'client_secret' => $clientSecret, - 'oauth_instance_url' => $oauthUrl, - 'use_popup' => $usePopup, - 'link_preview_enabled' => $adminLinkPreviewEnabled, - ]; - $this->initialStateService->provideInitialState('admin-config', $adminConfig); + $this->initialStateService->provideInitialState('admin-config', AdminConfig::loadConfig($this->config)->toArray()); return new TemplateResponse(Application::APP_ID, 'adminSettings'); } diff --git a/lib/Settings/Personal.php b/lib/Settings/Personal.php index 7051969..4f5fd9e 100644 --- a/lib/Settings/Personal.php +++ b/lib/Settings/Personal.php @@ -3,57 +3,26 @@ namespace OCA\Gitlab\Settings; use OCA\Gitlab\AppInfo\Application; +use OCA\Gitlab\Model\UserConfig; +use OCA\Gitlab\Service\ConfigService; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; -use OCP\IConfig; - use OCP\Settings\ISettings; class Personal implements ISettings { - public function __construct(private IConfig $config, + public function __construct( + private ConfigService $config, private IInitialState $initialStateService, - private ?string $userId) { + private string $userId, + ) { } /** * @return TemplateResponse */ public function getForm(): TemplateResponse { - // Do not expose the saved token to the user - $token = $this->config->getUserValue($this->userId, Application::APP_ID, 'token') !== '' ? 'dummyToken' : ''; - $searchEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'search_enabled', '0') === '1'; - $searchIssuesEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'search_issues_enabled', '0') === '1'; - $searchMRsEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'search_mrs_enabled', '0') === '1'; - $linkPreviewEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'link_preview_enabled', '1') === '1'; - - $userName = $this->config->getUserValue($this->userId, Application::APP_ID, 'user_name'); - $userDisplayName = $this->config->getUserValue($this->userId, Application::APP_ID, 'user_displayname'); - - // for OAuth - $clientID = $this->config->getAppValue(Application::APP_ID, 'client_id'); - // don't expose the client secret to users - $clientSecret = ($this->config->getAppValue(Application::APP_ID, 'client_secret') !== ''); - $adminOauthUrl = $this->config->getAppValue(Application::APP_ID, 'oauth_instance_url', Application::DEFAULT_GITLAB_URL) ?: Application::DEFAULT_GITLAB_URL; - $usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0'); - - $url = $this->config->getUserValue($this->userId, Application::APP_ID, 'url', $adminOauthUrl) ?: $adminOauthUrl; - - $userConfig = [ - 'token' => $token, - 'url' => $url, - 'client_id' => $clientID, - 'client_secret' => $clientSecret, - 'oauth_instance_url' => $adminOauthUrl, - 'use_popup' => ($usePopup === '1'), - 'user_name' => $userName, - 'user_displayname' => $userDisplayName, - 'search_enabled' => $searchEnabled, - 'search_issues_enabled' => $searchIssuesEnabled, - 'search_mrs_enabled' => $searchMRsEnabled, - 'link_preview_enabled' => $linkPreviewEnabled, - ]; - $this->initialStateService->provideInitialState('user-config', $userConfig); + $this->initialStateService->provideInitialState('user-config', UserConfig::loadConfig($this->userId, $this->config)->toArray()); return new TemplateResponse(Application::APP_ID, 'personalSettings'); } diff --git a/src/components/AdminSettings.vue b/src/components/AdminSettings.vue index 3989491..1180a44 100644 --- a/src/components/AdminSettings.vue +++ b/src/components/AdminSettings.vue @@ -120,7 +120,7 @@ export default { onCheckboxChanged(newValue, key) { this.state[key] = newValue axios.put(generateUrl('/apps/integration_gitlab/admin-config'), { - values: { [key]: this.state[key] ? '1' : '0' }, + values: { [key]: this.state[key] }, }).then((response) => { showSuccess(t('integration_gitlab', 'GitLab admin options saved')) }).catch((error) => { diff --git a/src/components/PersonalSettings.vue b/src/components/PersonalSettings.vue index 6d8ca6f..ac97220 100644 --- a/src/components/PersonalSettings.vue +++ b/src/components/PersonalSettings.vue @@ -179,7 +179,7 @@ export default { try { await axios.put(generateUrl('/apps/integration_gitlab/config'), { - values: { [key]: this.state[key] ? '1' : '0' }, + values: { [key]: this.state[key] }, }) showSuccess(t('integration_gitlab', 'GitLab options saved')) } catch (error) { diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 1066c4c..0a00170 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,6 +1,7 @@ method('newClient')->willReturn($this->iClient); $this->gitlabApiService = new GitlabAPIService( - self::APP_NAME, \OC::$server->get(\Psr\Log\LoggerInterface::class), $this->createMock(IL10N::class), - \OC::$server->get(IConfig::class), + \OC::$server->get(ConfigService::class), $clientService, ); $this->gitlabApiController = new GitlabAPIController( self::APP_NAME, $this->createMock(IRequest::class), - \OC::$server->get(IConfig::class), + \OC::$server->get(ConfigService::class), \OC::$server->get(IURLGenerator::class), $this->gitlabApiService, self::TEST_USER1 ); - $this->config = \OC::$server->get(IConfig::class); - $this->config->setUserValue(self::TEST_USER1, Application::APP_ID, 'token', self::API_TOKEN); + $this->config = \OC::$server->get(ConfigService::class); + $this->config->setUserToken(self::TEST_USER1, self::API_TOKEN); + $this->config->setUserUrl(self::TEST_USER1, Application::DEFAULT_GITLAB_URL); } public function testGetUserAvatar(): void {