From 88d6c8eec3ecf97a32a7f97f703c3fb733bbefc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 2 Oct 2023 17:13:32 +0200 Subject: [PATCH 01/11] Add ClientDiagnostic mapper and controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- apps/settings/appinfo/routes.php | 1 + .../composer/composer/autoload_classmap.php | 3 + .../composer/composer/autoload_static.php | 3 + .../ClientDiagnosticsController.php | 78 +++++++++++++++++++ apps/settings/lib/Db/ClientDiagnostic.php | 47 +++++++++++ .../lib/Db/ClientDiagnosticMapper.php | 39 ++++++++++ 6 files changed, 171 insertions(+) create mode 100644 apps/settings/lib/Controller/ClientDiagnosticsController.php create mode 100644 apps/settings/lib/Db/ClientDiagnostic.php create mode 100644 apps/settings/lib/Db/ClientDiagnosticMapper.php diff --git a/apps/settings/appinfo/routes.php b/apps/settings/appinfo/routes.php index e238510b1a75f..9d56c1010ea43 100644 --- a/apps/settings/appinfo/routes.php +++ b/apps/settings/appinfo/routes.php @@ -36,6 +36,7 @@ ['name' => 'AuthorizedGroup#destroy', 'url' => '/settings/authorizedgroups', 'verb' => 'DELETE'], ['name' => 'AuthSettings#wipe', 'url' => '/settings/personal/authtokens/wipe/{id}', 'verb' => 'POST' , 'root' => ''], + ['name' => 'ClientDiagnostics#update', 'url' => '/settings/diagnostics', 'verb' => 'PUT' , 'root' => ''], ['name' => 'MailSettings#setMailSettings', 'url' => '/settings/admin/mailsettings', 'verb' => 'POST' , 'root' => ''], ['name' => 'MailSettings#storeCredentials', 'url' => '/settings/admin/mailsettings/credentials', 'verb' => 'POST' , 'root' => ''], diff --git a/apps/settings/composer/composer/autoload_classmap.php b/apps/settings/composer/composer/autoload_classmap.php index 674b92b7cac36..11b842c8fecad 100644 --- a/apps/settings/composer/composer/autoload_classmap.php +++ b/apps/settings/composer/composer/autoload_classmap.php @@ -23,6 +23,7 @@ 'OCA\\Settings\\Controller\\AuthorizedGroupController' => $baseDir . '/../lib/Controller/AuthorizedGroupController.php', 'OCA\\Settings\\Controller\\ChangePasswordController' => $baseDir . '/../lib/Controller/ChangePasswordController.php', 'OCA\\Settings\\Controller\\CheckSetupController' => $baseDir . '/../lib/Controller/CheckSetupController.php', + 'OCA\\Settings\\Controller\\ClientDiagnosticsController' => $baseDir . '/../lib/Controller/ClientDiagnosticsController.php', 'OCA\\Settings\\Controller\\CommonSettingsTrait' => $baseDir . '/../lib/Controller/CommonSettingsTrait.php', 'OCA\\Settings\\Controller\\HelpController' => $baseDir . '/../lib/Controller/HelpController.php', 'OCA\\Settings\\Controller\\LogSettingsController' => $baseDir . '/../lib/Controller/LogSettingsController.php', @@ -32,6 +33,8 @@ 'OCA\\Settings\\Controller\\TwoFactorSettingsController' => $baseDir . '/../lib/Controller/TwoFactorSettingsController.php', 'OCA\\Settings\\Controller\\UsersController' => $baseDir . '/../lib/Controller/UsersController.php', 'OCA\\Settings\\Controller\\WebAuthnController' => $baseDir . '/../lib/Controller/WebAuthnController.php', + 'OCA\\Settings\\Db\\ClientDiagnostic' => $baseDir . '/../lib/Db/ClientDiagnostic.php', + 'OCA\\Settings\\Db\\ClientDiagnosticMapper' => $baseDir . '/../lib/Db/ClientDiagnosticMapper.php', 'OCA\\Settings\\Events\\BeforeTemplateRenderedEvent' => $baseDir . '/../lib/Events/BeforeTemplateRenderedEvent.php', 'OCA\\Settings\\Hooks' => $baseDir . '/../lib/Hooks.php', 'OCA\\Settings\\Listener\\AppPasswordCreatedActivityListener' => $baseDir . '/../lib/Listener/AppPasswordCreatedActivityListener.php', diff --git a/apps/settings/composer/composer/autoload_static.php b/apps/settings/composer/composer/autoload_static.php index d78aa56c60642..06f02fd0ed3be 100644 --- a/apps/settings/composer/composer/autoload_static.php +++ b/apps/settings/composer/composer/autoload_static.php @@ -38,6 +38,7 @@ class ComposerStaticInitSettings 'OCA\\Settings\\Controller\\AuthorizedGroupController' => __DIR__ . '/..' . '/../lib/Controller/AuthorizedGroupController.php', 'OCA\\Settings\\Controller\\ChangePasswordController' => __DIR__ . '/..' . '/../lib/Controller/ChangePasswordController.php', 'OCA\\Settings\\Controller\\CheckSetupController' => __DIR__ . '/..' . '/../lib/Controller/CheckSetupController.php', + 'OCA\\Settings\\Controller\\ClientDiagnosticsController' => __DIR__ . '/..' . '/../lib/Controller/ClientDiagnosticsController.php', 'OCA\\Settings\\Controller\\CommonSettingsTrait' => __DIR__ . '/..' . '/../lib/Controller/CommonSettingsTrait.php', 'OCA\\Settings\\Controller\\HelpController' => __DIR__ . '/..' . '/../lib/Controller/HelpController.php', 'OCA\\Settings\\Controller\\LogSettingsController' => __DIR__ . '/..' . '/../lib/Controller/LogSettingsController.php', @@ -47,6 +48,8 @@ class ComposerStaticInitSettings 'OCA\\Settings\\Controller\\TwoFactorSettingsController' => __DIR__ . '/..' . '/../lib/Controller/TwoFactorSettingsController.php', 'OCA\\Settings\\Controller\\UsersController' => __DIR__ . '/..' . '/../lib/Controller/UsersController.php', 'OCA\\Settings\\Controller\\WebAuthnController' => __DIR__ . '/..' . '/../lib/Controller/WebAuthnController.php', + 'OCA\\Settings\\Db\\ClientDiagnostic' => __DIR__ . '/..' . '/../lib/Db/ClientDiagnostic.php', + 'OCA\\Settings\\Db\\ClientDiagnosticMapper' => __DIR__ . '/..' . '/../lib/Db/ClientDiagnosticMapper.php', 'OCA\\Settings\\Events\\BeforeTemplateRenderedEvent' => __DIR__ . '/..' . '/../lib/Events/BeforeTemplateRenderedEvent.php', 'OCA\\Settings\\Hooks' => __DIR__ . '/..' . '/../lib/Hooks.php', 'OCA\\Settings\\Listener\\AppPasswordCreatedActivityListener' => __DIR__ . '/..' . '/../lib/Listener/AppPasswordCreatedActivityListener.php', diff --git a/apps/settings/lib/Controller/ClientDiagnosticsController.php b/apps/settings/lib/Controller/ClientDiagnosticsController.php new file mode 100644 index 0000000000000..73442af388ca6 --- /dev/null +++ b/apps/settings/lib/Controller/ClientDiagnosticsController.php @@ -0,0 +1,78 @@ + + * + * @author Côme Chilliet + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Settings\Controller; + +use OC\Authentication\Exceptions\InvalidTokenException; +use OC\Authentication\Token\IProvider; +use OCA\Settings\Db\ClientDiagnostics; +use OCA\Settings\Db\ClientDiagnosticsMapper; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; +use OCP\IRequest; +use OCP\ISession; +use OCP\IUserSession; +use OCP\Session\Exceptions\SessionNotAvailableException; + +class ClientDiagnosticsController extends Controller { + public function __construct( + string $appName, + IRequest $request, + private ISession $session, + private IUserSession $userSession, + private ClientDiagnosticsMapper $mapper, + private IProvider $tokenProvider, + ) { + parent::__construct($appName, $request); + } + + /** + * @NoAdminRequired + * @NoSubAdminRequired + */ + public function update(string $data): DataResponse { + try { + $sessionId = $this->session->getId(); + } catch (SessionNotAvailableException $e) { + return new DataResponse(['message' => $e->getMessage()], Http::STATUS_SERVICE_UNAVAILABLE); + } + if ($this->userSession->getImpersonatingUserID() !== null) { + return new DataResponse([], Http::STATUS_METHOD_NOT_ALLOWED); + } + + $appPassword = $this->session->get('app_password'); + + try { + $token = $this->tokenProvider->getToken($appPassword); + } catch (InvalidTokenException $e) { + return new DataResponse([], Http::STATUS_METHOD_NOT_ALLOWED); + } + + $entity = $this->mapper->insertOrUpdate(new ClientDiagnostics($token->getId(), $data)); + + return new DataResponse([]); + } +} diff --git a/apps/settings/lib/Db/ClientDiagnostic.php b/apps/settings/lib/Db/ClientDiagnostic.php new file mode 100644 index 0000000000000..df86fddd4ec2a --- /dev/null +++ b/apps/settings/lib/Db/ClientDiagnostic.php @@ -0,0 +1,47 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Settings\Db; + +use OCP\AppFramework\Db\Entity; +use OCP\DB\Types; + +/** + * @method void setAuthtokenid(int $authtokenid) + * @method int getAuthtokenid() + */ +class ClientDiagnostic extends Entity { + /** @var int */ + protected $authtokenid; + + /** @var string json-encoded*/ + protected $diagnostic; + + public function __construct() { + $this->addType('authtokenid', Types::BIGINT); + $this->addType('diagnostic', Types::TEXT); + } +} diff --git a/apps/settings/lib/Db/ClientDiagnosticMapper.php b/apps/settings/lib/Db/ClientDiagnosticMapper.php new file mode 100644 index 0000000000000..07eb1495da2cf --- /dev/null +++ b/apps/settings/lib/Db/ClientDiagnosticMapper.php @@ -0,0 +1,39 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Settings\Db; + +use OCP\AppFramework\Db\QBMapper; +use OCP\IDBConnection; + +/** + * @template-extends QBMapper + */ +class ClientDiagnosticMapper extends QBMapper { + public function __construct(IDBConnection $db) { + parent::__construct($db, 'client_diagnostics', ClientDiagnostic::class); + } +} From 86fd999e64d7842dd7ca9e4ddfbaca2fd505b554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 2 Oct 2023 17:22:38 +0200 Subject: [PATCH 02/11] Add migration to create DB table for client diagnostics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- .../lib/Db/ClientDiagnosticMapper.php | 4 +- .../Version28000Date20231002171502.php | 72 +++++++++++++++++++ lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_static.php | 1 + 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 core/Migrations/Version28000Date20231002171502.php diff --git a/apps/settings/lib/Db/ClientDiagnosticMapper.php b/apps/settings/lib/Db/ClientDiagnosticMapper.php index 07eb1495da2cf..79b1f72c4ae8c 100644 --- a/apps/settings/lib/Db/ClientDiagnosticMapper.php +++ b/apps/settings/lib/Db/ClientDiagnosticMapper.php @@ -33,7 +33,9 @@ * @template-extends QBMapper */ class ClientDiagnosticMapper extends QBMapper { + public const TABLE_NAME = 'client_diagnostics'; + public function __construct(IDBConnection $db) { - parent::__construct($db, 'client_diagnostics', ClientDiagnostic::class); + parent::__construct($db, self::TABLE_NAME, ClientDiagnostic::class); } } diff --git a/core/Migrations/Version28000Date20231002171502.php b/core/Migrations/Version28000Date20231002171502.php new file mode 100644 index 0000000000000..1de7b9ee2d75d --- /dev/null +++ b/core/Migrations/Version28000Date20231002171502.php @@ -0,0 +1,72 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\Core\Migrations; + +use Closure; +use OCA\Settings\Db\ClientDiagnosticMapper; +use OCP\DB\ISchemaWrapper; +use OCP\DB\Types; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +/** + * Introduce client_diagnostics table + */ +class Version28000Date20231002171502 extends SimpleMigrationStep { + /** + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + if (!$schema->hasTable(ClientDiagnosticMapper::TABLE_NAME)) { + $table = $schema->createTable(ClientDiagnosticMapper::TABLE_NAME); + + $table->addColumn('id', Types::BIGINT, [ + 'notnull' => true, + 'length' => 64, + 'autoincrement' => true, + ]); + $table->addColumn('authtokenid', Types::BIGINT, [ + 'notnull' => true, + 'length' => 64, + ]); + $table->addColumn('diagnostic', Types::TEXT, [ + 'notnull' => true, + ]); + + $table->setPrimaryKey(['id'], 'client_diagnostics_id_primary'); + $table->addUniqueIndex(['authtokenid'], 'client_diagnostics_authtokenid_index'); + + $changed = true; + return $schema; + } + + return null; + } +} diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 6e5bf85efcf93..1f123678f89d3 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1174,6 +1174,7 @@ 'OC\\Core\\Migrations\\Version28000Date20230616104802' => $baseDir . '/core/Migrations/Version28000Date20230616104802.php', 'OC\\Core\\Migrations\\Version28000Date20230728104802' => $baseDir . '/core/Migrations/Version28000Date20230728104802.php', 'OC\\Core\\Migrations\\Version28000Date20230803221055' => $baseDir . '/core/Migrations/Version28000Date20230803221055.php', + 'OC\\Core\\Migrations\\Version28000Date20231002171502' => $baseDir . '/core/Migrations/Version28000Date20231002171502.php', 'OC\\Core\\Notification\\CoreNotifier' => $baseDir . '/core/Notification/CoreNotifier.php', 'OC\\Core\\Service\\LoginFlowV2Service' => $baseDir . '/core/Service/LoginFlowV2Service.php', 'OC\\DB\\Adapter' => $baseDir . '/lib/private/DB/Adapter.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index ef88bcd2a9b19..c63f35f188720 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1207,6 +1207,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Migrations\\Version28000Date20230616104802' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20230616104802.php', 'OC\\Core\\Migrations\\Version28000Date20230728104802' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20230728104802.php', 'OC\\Core\\Migrations\\Version28000Date20230803221055' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20230803221055.php', + 'OC\\Core\\Migrations\\Version28000Date20231002171502' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20231002171502.php', 'OC\\Core\\Notification\\CoreNotifier' => __DIR__ . '/../../..' . '/core/Notification/CoreNotifier.php', 'OC\\Core\\Service\\LoginFlowV2Service' => __DIR__ . '/../../..' . '/core/Service/LoginFlowV2Service.php', 'OC\\DB\\Adapter' => __DIR__ . '/../../..' . '/lib/private/DB/Adapter.php', From 468760314493ceceaeed4e21115a6a396abe9460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 2 Oct 2023 17:35:04 +0200 Subject: [PATCH 03/11] json_encode client diagnostic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- .../Controller/ClientDiagnosticsController.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/settings/lib/Controller/ClientDiagnosticsController.php b/apps/settings/lib/Controller/ClientDiagnosticsController.php index 73442af388ca6..08508722896e7 100644 --- a/apps/settings/lib/Controller/ClientDiagnosticsController.php +++ b/apps/settings/lib/Controller/ClientDiagnosticsController.php @@ -27,8 +27,8 @@ use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Token\IProvider; -use OCA\Settings\Db\ClientDiagnostics; -use OCA\Settings\Db\ClientDiagnosticsMapper; +use OCA\Settings\Db\ClientDiagnostic; +use OCA\Settings\Db\ClientDiagnosticMapper; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; @@ -43,7 +43,7 @@ public function __construct( IRequest $request, private ISession $session, private IUserSession $userSession, - private ClientDiagnosticsMapper $mapper, + private ClientDiagnosticMapper $mapper, private IProvider $tokenProvider, ) { parent::__construct($appName, $request); @@ -53,7 +53,7 @@ public function __construct( * @NoAdminRequired * @NoSubAdminRequired */ - public function update(string $data): DataResponse { + public function update(array $data): DataResponse { try { $sessionId = $this->session->getId(); } catch (SessionNotAvailableException $e) { @@ -71,7 +71,13 @@ public function update(string $data): DataResponse { return new DataResponse([], Http::STATUS_METHOD_NOT_ALLOWED); } - $entity = $this->mapper->insertOrUpdate(new ClientDiagnostics($token->getId(), $data)); + /* TODO: validate data structure */ + + $entity = $this->mapper->insertOrUpdate( + ClientDiagnostic::fromParams([ + 'authtokenid' => $token->getId(), + 'diagnostic' => json_encode($data), + ])); return new DataResponse([]); } From e67969eaa5c473a4b5a264246b709adf58eb6981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 2 Oct 2023 17:50:51 +0200 Subject: [PATCH 04/11] Add OCP API to register account warnings providers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- lib/composer/composer/autoload_classmap.php | 2 + lib/composer/composer/autoload_static.php | 2 + .../Bootstrap/IRegistrationContext.php | 10 ++++ lib/public/Settings/IAccountWarning.php | 49 +++++++++++++++++++ .../Settings/IAccountWarningsProvider.php | 44 +++++++++++++++++ 5 files changed, 107 insertions(+) create mode 100644 lib/public/Settings/IAccountWarning.php create mode 100644 lib/public/Settings/IAccountWarningsProvider.php diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 1f123678f89d3..d3082c2b5a446 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -595,6 +595,8 @@ 'OCP\\Security\\VerificationToken\\InvalidTokenException' => $baseDir . '/lib/public/Security/VerificationToken/InvalidTokenException.php', 'OCP\\Server' => $baseDir . '/lib/public/Server.php', 'OCP\\Session\\Exceptions\\SessionNotAvailableException' => $baseDir . '/lib/public/Session/Exceptions/SessionNotAvailableException.php', + 'OCP\\Settings\\IAccountWarning' => $baseDir . '/lib/public/Settings/IAccountWarning.php', + 'OCP\\Settings\\IAccountWarningsProvider' => $baseDir . '/lib/public/Settings/IAccountWarningsProvider.php', 'OCP\\Settings\\IDelegatedSettings' => $baseDir . '/lib/public/Settings/IDelegatedSettings.php', 'OCP\\Settings\\IIconSection' => $baseDir . '/lib/public/Settings/IIconSection.php', 'OCP\\Settings\\IManager' => $baseDir . '/lib/public/Settings/IManager.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index c63f35f188720..6d763a2689485 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -628,6 +628,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Security\\VerificationToken\\InvalidTokenException' => __DIR__ . '/../../..' . '/lib/public/Security/VerificationToken/InvalidTokenException.php', 'OCP\\Server' => __DIR__ . '/../../..' . '/lib/public/Server.php', 'OCP\\Session\\Exceptions\\SessionNotAvailableException' => __DIR__ . '/../../..' . '/lib/public/Session/Exceptions/SessionNotAvailableException.php', + 'OCP\\Settings\\IAccountWarning' => __DIR__ . '/../../..' . '/lib/public/Settings/IAccountWarning.php', + 'OCP\\Settings\\IAccountWarningsProvider' => __DIR__ . '/../../..' . '/lib/public/Settings/IAccountWarningsProvider.php', 'OCP\\Settings\\IDelegatedSettings' => __DIR__ . '/../../..' . '/lib/public/Settings/IDelegatedSettings.php', 'OCP\\Settings\\IIconSection' => __DIR__ . '/../../..' . '/lib/public/Settings/IIconSection.php', 'OCP\\Settings\\IManager' => __DIR__ . '/../../..' . '/lib/public/Settings/IManager.php', diff --git a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php index 720803a78d170..b4f252daf43b8 100644 --- a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php +++ b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php @@ -371,4 +371,14 @@ public function registerSensitiveMethods(string $class, array $methods): void; * @since 26.0.0 */ public function registerPublicShareTemplateProvider(string $class): void; + + /** + * Register an implementation of IAccountWarningsProvider. + * + * @param string $class + * @psalm-param class-string<\OCP\Settings\IAccountWarningsProvider> $class + * @return void + * @since 28.0.0 + */ + public function registerAccountWarningsProvider(string $class): void; } diff --git a/lib/public/Settings/IAccountWarning.php b/lib/public/Settings/IAccountWarning.php new file mode 100644 index 0000000000000..d23dc70e0dbfa --- /dev/null +++ b/lib/public/Settings/IAccountWarning.php @@ -0,0 +1,49 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCP\Settings; + +/** + * @since 28.0.0 + */ +interface IAccountWarning { + public const SEVERITY_INFO = 'info'; + public const SEVERITY_WARNING = 'warning'; + public const SEVERITY_ERROR = 'error'; + + /** + * Text to show to the admin + * @since 28.0.0 + */ + public function getText(): string; + + /** + * Severity, one the SEVERITY_* constants + * @return self::SEVERITY_INFO|self::SEVERITY_WARNING|self::SEVERITY_ERROR + * @since 28.0.0 + */ + public function getSeverity(): string; +} diff --git a/lib/public/Settings/IAccountWarningsProvider.php b/lib/public/Settings/IAccountWarningsProvider.php new file mode 100644 index 0000000000000..67a12e2146568 --- /dev/null +++ b/lib/public/Settings/IAccountWarningsProvider.php @@ -0,0 +1,44 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCP\Settings; + +/** + * @since 28.0.0 + */ +interface IAccountWarningsProvider { + /** + * @return IAccountWarning[] Warnings detected by this provider + * @since 28.0.0 + */ + public function getAccountWarnings(): array; + + /** + * Name to show as tab name in the UI + * @since 28.0.0 + */ + public function getName(): string; +} From f398b31d96b9d0d985cfa331575a0dce41170c3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Mon, 2 Oct 2023 18:10:34 +0200 Subject: [PATCH 05/11] Add a provider of account warnings for outdated clients MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stub for now Signed-off-by: Côme Chilliet --- .../composer/composer/autoload_classmap.php | 2 + .../composer/composer/autoload_static.php | 2 + .../AccountWarnings/OutdatedClientWarning.php | 46 +++++++++++++++++++ .../OutdatedClientWarningsProvider.php | 44 ++++++++++++++++++ apps/settings/lib/AppInfo/Application.php | 3 ++ 5 files changed, 97 insertions(+) create mode 100644 apps/settings/lib/AccountWarnings/OutdatedClientWarning.php create mode 100644 apps/settings/lib/AccountWarnings/OutdatedClientWarningsProvider.php diff --git a/apps/settings/composer/composer/autoload_classmap.php b/apps/settings/composer/composer/autoload_classmap.php index 11b842c8fecad..65c149d48a6a9 100644 --- a/apps/settings/composer/composer/autoload_classmap.php +++ b/apps/settings/composer/composer/autoload_classmap.php @@ -7,6 +7,8 @@ return array( 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', + 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarning' => $baseDir . '/../lib/AccountWarnings/OutdatedClientWarning.php', + 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarningsProvider' => $baseDir . '/../lib/AccountWarnings/OutdatedClientWarningsProvider.php', 'OCA\\Settings\\Activity\\GroupProvider' => $baseDir . '/../lib/Activity/GroupProvider.php', 'OCA\\Settings\\Activity\\GroupSetting' => $baseDir . '/../lib/Activity/GroupSetting.php', 'OCA\\Settings\\Activity\\Provider' => $baseDir . '/../lib/Activity/Provider.php', diff --git a/apps/settings/composer/composer/autoload_static.php b/apps/settings/composer/composer/autoload_static.php index 06f02fd0ed3be..cd593e6373d1c 100644 --- a/apps/settings/composer/composer/autoload_static.php +++ b/apps/settings/composer/composer/autoload_static.php @@ -22,6 +22,8 @@ class ComposerStaticInitSettings public static $classMap = array ( 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarning' => __DIR__ . '/..' . '/../lib/AccountWarnings/OutdatedClientWarning.php', + 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarningsProvider' => __DIR__ . '/..' . '/../lib/AccountWarnings/OutdatedClientWarningsProvider.php', 'OCA\\Settings\\Activity\\GroupProvider' => __DIR__ . '/..' . '/../lib/Activity/GroupProvider.php', 'OCA\\Settings\\Activity\\GroupSetting' => __DIR__ . '/..' . '/../lib/Activity/GroupSetting.php', 'OCA\\Settings\\Activity\\Provider' => __DIR__ . '/..' . '/../lib/Activity/Provider.php', diff --git a/apps/settings/lib/AccountWarnings/OutdatedClientWarning.php b/apps/settings/lib/AccountWarnings/OutdatedClientWarning.php new file mode 100644 index 0000000000000..726eee1c9cd94 --- /dev/null +++ b/apps/settings/lib/AccountWarnings/OutdatedClientWarning.php @@ -0,0 +1,46 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Settings\AccountWarnings; + +use OCP\Settings\IAccountWarning; +use OCP\IL10N; + +class OutdatedClientWarning implements IAccountWarning { + public function __construct( + private IL10N $l10n, + private int $count, + private string $version, + ) { + } + + public function getText(): string { + return $this->l10n->t('%d users are using outdated client version "%s"', [$this->count, $this->version]); + } + + public function getSeverity(): string { + return IAccountWarning::SEVERITY_WARNING; + } +} diff --git a/apps/settings/lib/AccountWarnings/OutdatedClientWarningsProvider.php b/apps/settings/lib/AccountWarnings/OutdatedClientWarningsProvider.php new file mode 100644 index 0000000000000..f5d9f0198847e --- /dev/null +++ b/apps/settings/lib/AccountWarnings/OutdatedClientWarningsProvider.php @@ -0,0 +1,44 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Settings\AccountWarnings; + +use OCP\Settings\IAccountWarningsProvider; +use OCP\IL10N; + +class OutdatedClientWarningsProvider implements IAccountWarningsProvider { + public function __construct( + private IL10N $l10n, + ) { + } + + public function getName(): string { + return $this->l10n->t('Outdated clients'); + } + + public function getAccountWarnings(): array { + return [new OutdatedClientWarning($this->l10n, 2, 'Example Desktop client 3.5.0')]; + } +} diff --git a/apps/settings/lib/AppInfo/Application.php b/apps/settings/lib/AppInfo/Application.php index 8d99f7f4f8687..50bd64196a720 100644 --- a/apps/settings/lib/AppInfo/Application.php +++ b/apps/settings/lib/AppInfo/Application.php @@ -37,6 +37,7 @@ use OC\Authentication\Events\AppPasswordCreatedEvent; use OC\Authentication\Token\IProvider; use OC\Server; +use OCA\Settings\AccountWarnings\OutdatedClientWarningsProvider; use OCA\Settings\Hooks; use OCA\Settings\Listener\AppPasswordCreatedActivityListener; use OCA\Settings\Listener\GroupRemovedListener; @@ -136,6 +137,8 @@ public function register(IRegistrationContext $context): void { }); $context->registerUserMigrator(AccountMigrator::class); + + $context->registerAccountWarningsProvider(OutdatedClientWarningsProvider::class); } public function boot(IBootContext $context): void { From a24a3d8545b8e0320e441a0b702a03f2c659961c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 3 Oct 2023 09:40:56 +0200 Subject: [PATCH 06/11] Implement account provider registration in RegistrationContext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- .../Bootstrap/RegistrationContext.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/private/AppFramework/Bootstrap/RegistrationContext.php b/lib/private/AppFramework/Bootstrap/RegistrationContext.php index 5aea2a7a744b0..ed137ac958cad 100644 --- a/lib/private/AppFramework/Bootstrap/RegistrationContext.php +++ b/lib/private/AppFramework/Bootstrap/RegistrationContext.php @@ -55,6 +55,7 @@ use OCP\Notification\INotifier; use OCP\Profile\ILinkAction; use OCP\Search\IProvider; +use OCP\Settings\IAccountWarningsProvider; use OCP\Share\IPublicShareTemplateProvider; use OCP\Support\CrashReport\IReporter; use OCP\UserMigration\IMigrator as IUserMigrator; @@ -146,6 +147,9 @@ class RegistrationContext { /** @var ServiceRegistration[] */ private $publicShareTemplateProviders = []; + /** @var ServiceRegistration[] */ + private array $accountWarningsProviders = []; + /** @var LoggerInterface */ private $logger; @@ -372,6 +376,13 @@ public function registerPublicShareTemplateProvider(string $class): void { $class ); } + + public function registerAccountWarningsProvider(string $class): void { + $this->context->registerAccountWarningsProvider( + $this->appId, + $class + ); + } }; } @@ -523,6 +534,10 @@ public function registerPublicShareTemplateProvider(string $appId, string $class $this->publicShareTemplateProviders[] = new ServiceRegistration($appId, $class); } + public function registerAccountWarningsProvider(string $appId, string $class): void { + $this->accountWarningsProviders[] = new ServiceRegistration($appId, $class); + } + /** * @param App[] $apps */ @@ -828,4 +843,11 @@ public function getSensitiveMethods(): array { public function getPublicShareTemplateProviders(): array { return $this->publicShareTemplateProviders; } + + /** + * @return ServiceRegistration[] + */ + public function getAccountWarningsProviders(): array { + return $this->accountWarningsProviders; + } } From b0528d3bf82bab60fffcf282db97d42454b0a4b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 3 Oct 2023 09:43:10 +0200 Subject: [PATCH 07/11] Add route to get account warnings from server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- apps/settings/appinfo/routes.php | 1 + .../composer/composer/autoload_classmap.php | 2 + .../composer/composer/autoload_static.php | 2 + .../AccountWarningsManager.php | 58 +++++++++++++++++++ .../Controller/AccountWarningsController.php | 45 ++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 apps/settings/lib/AccountWarnings/AccountWarningsManager.php create mode 100644 apps/settings/lib/Controller/AccountWarningsController.php diff --git a/apps/settings/appinfo/routes.php b/apps/settings/appinfo/routes.php index 9d56c1010ea43..48f9fd8a0a639 100644 --- a/apps/settings/appinfo/routes.php +++ b/apps/settings/appinfo/routes.php @@ -37,6 +37,7 @@ ['name' => 'AuthSettings#wipe', 'url' => '/settings/personal/authtokens/wipe/{id}', 'verb' => 'POST' , 'root' => ''], ['name' => 'ClientDiagnostics#update', 'url' => '/settings/diagnostics', 'verb' => 'PUT' , 'root' => ''], + ['name' => 'AccountWarnings#getAll', 'url' => '/settings/accountwarnings', 'verb' => 'GET' , 'root' => ''], ['name' => 'MailSettings#setMailSettings', 'url' => '/settings/admin/mailsettings', 'verb' => 'POST' , 'root' => ''], ['name' => 'MailSettings#storeCredentials', 'url' => '/settings/admin/mailsettings/credentials', 'verb' => 'POST' , 'root' => ''], diff --git a/apps/settings/composer/composer/autoload_classmap.php b/apps/settings/composer/composer/autoload_classmap.php index 65c149d48a6a9..bd272d23d36cc 100644 --- a/apps/settings/composer/composer/autoload_classmap.php +++ b/apps/settings/composer/composer/autoload_classmap.php @@ -7,6 +7,7 @@ return array( 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', + 'OCA\\Settings\\AccountWarnings\\AccountWarningsManager' => $baseDir . '/../lib/AccountWarnings/AccountWarningsManager.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarning' => $baseDir . '/../lib/AccountWarnings/OutdatedClientWarning.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarningsProvider' => $baseDir . '/../lib/AccountWarnings/OutdatedClientWarningsProvider.php', 'OCA\\Settings\\Activity\\GroupProvider' => $baseDir . '/../lib/Activity/GroupProvider.php', @@ -19,6 +20,7 @@ 'OCA\\Settings\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php', 'OCA\\Settings\\BackgroundJobs\\VerifyUserData' => $baseDir . '/../lib/BackgroundJobs/VerifyUserData.php', 'OCA\\Settings\\Controller\\AISettingsController' => $baseDir . '/../lib/Controller/AISettingsController.php', + 'OCA\\Settings\\Controller\\AccountWarningsController' => $baseDir . '/../lib/Controller/AccountWarningsController.php', 'OCA\\Settings\\Controller\\AdminSettingsController' => $baseDir . '/../lib/Controller/AdminSettingsController.php', 'OCA\\Settings\\Controller\\AppSettingsController' => $baseDir . '/../lib/Controller/AppSettingsController.php', 'OCA\\Settings\\Controller\\AuthSettingsController' => $baseDir . '/../lib/Controller/AuthSettingsController.php', diff --git a/apps/settings/composer/composer/autoload_static.php b/apps/settings/composer/composer/autoload_static.php index cd593e6373d1c..4984a706ec8ca 100644 --- a/apps/settings/composer/composer/autoload_static.php +++ b/apps/settings/composer/composer/autoload_static.php @@ -22,6 +22,7 @@ class ComposerStaticInitSettings public static $classMap = array ( 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'OCA\\Settings\\AccountWarnings\\AccountWarningsManager' => __DIR__ . '/..' . '/../lib/AccountWarnings/AccountWarningsManager.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarning' => __DIR__ . '/..' . '/../lib/AccountWarnings/OutdatedClientWarning.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarningsProvider' => __DIR__ . '/..' . '/../lib/AccountWarnings/OutdatedClientWarningsProvider.php', 'OCA\\Settings\\Activity\\GroupProvider' => __DIR__ . '/..' . '/../lib/Activity/GroupProvider.php', @@ -34,6 +35,7 @@ class ComposerStaticInitSettings 'OCA\\Settings\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php', 'OCA\\Settings\\BackgroundJobs\\VerifyUserData' => __DIR__ . '/..' . '/../lib/BackgroundJobs/VerifyUserData.php', 'OCA\\Settings\\Controller\\AISettingsController' => __DIR__ . '/..' . '/../lib/Controller/AISettingsController.php', + 'OCA\\Settings\\Controller\\AccountWarningsController' => __DIR__ . '/..' . '/../lib/Controller/AccountWarningsController.php', 'OCA\\Settings\\Controller\\AdminSettingsController' => __DIR__ . '/..' . '/../lib/Controller/AdminSettingsController.php', 'OCA\\Settings\\Controller\\AppSettingsController' => __DIR__ . '/..' . '/../lib/Controller/AppSettingsController.php', 'OCA\\Settings\\Controller\\AuthSettingsController' => __DIR__ . '/..' . '/../lib/Controller/AuthSettingsController.php', diff --git a/apps/settings/lib/AccountWarnings/AccountWarningsManager.php b/apps/settings/lib/AccountWarnings/AccountWarningsManager.php new file mode 100644 index 0000000000000..70f61f7251c06 --- /dev/null +++ b/apps/settings/lib/AccountWarnings/AccountWarningsManager.php @@ -0,0 +1,58 @@ + + * + * @author Côme Chilliet + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Settings\AccountWarnings; + +use OCP\Settings\IAccountWarningsProvider; +use OC\AppFramework\Bootstrap\Coordinator; + +class AccountWarningsManager { + public function __construct( + private Coordinator $coordinator, + ) { + } + + /** + * @return array}> + */ + public function getAll(): array { + $results = []; + $providerRegistrations = $this->coordinator->getRegistrationContext()->getAccountWarningsProviders(); + foreach ($providerRegistrations as $providerRegistration) { + /** @var IAccountWarningsProvider $provider */ + $provider = \OCP\Server::get($providerRegistration->getService()); + $warnings = $provider->getAccountWarnings(); + $results[$provider::class] = ['name' => $provider->getName(),'warnings' => []]; + foreach ($warnings as $warning) { + $category = $warning->getSeverity(); + if (!isset($results[$provider::class]['warnings'][$category])) { + $results[$provider::class]['warnings'][$category] = []; + } + $results[$provider::class]['warnings'][$category][] = $warning->getText(); + } + } + return $results; + } +} diff --git a/apps/settings/lib/Controller/AccountWarningsController.php b/apps/settings/lib/Controller/AccountWarningsController.php new file mode 100644 index 0000000000000..8b76a6a06e85b --- /dev/null +++ b/apps/settings/lib/Controller/AccountWarningsController.php @@ -0,0 +1,45 @@ + + * + * @author Côme Chilliet + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Settings\Controller; + +use OCA\Settings\AccountWarnings\AccountWarningsManager; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\DataResponse; +use OCP\IRequest; + +class AccountWarningsController extends Controller { + public function __construct( + string $appName, + IRequest $request, + private AccountWarningsManager $manager, + ) { + parent::__construct($appName, $request); + } + + public function getAll(): DataResponse { + return new DataResponse($this->manager->getAll()); + } +} From d01ad74b0b22276149e7acdf34060a48617d3278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 3 Oct 2023 14:26:32 +0200 Subject: [PATCH 08/11] Add QuotaWarningsProvider to warn about account close to full quota MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- .../composer/composer/autoload_classmap.php | 2 + .../composer/composer/autoload_static.php | 2 + .../lib/AccountWarnings/QuotaWarning.php | 57 ++++++++++++++ .../AccountWarnings/QuotaWarningsProvider.php | 75 +++++++++++++++++++ apps/settings/lib/AppInfo/Application.php | 2 + 5 files changed, 138 insertions(+) create mode 100644 apps/settings/lib/AccountWarnings/QuotaWarning.php create mode 100644 apps/settings/lib/AccountWarnings/QuotaWarningsProvider.php diff --git a/apps/settings/composer/composer/autoload_classmap.php b/apps/settings/composer/composer/autoload_classmap.php index bd272d23d36cc..2dc6b4a9f3103 100644 --- a/apps/settings/composer/composer/autoload_classmap.php +++ b/apps/settings/composer/composer/autoload_classmap.php @@ -10,6 +10,8 @@ 'OCA\\Settings\\AccountWarnings\\AccountWarningsManager' => $baseDir . '/../lib/AccountWarnings/AccountWarningsManager.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarning' => $baseDir . '/../lib/AccountWarnings/OutdatedClientWarning.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarningsProvider' => $baseDir . '/../lib/AccountWarnings/OutdatedClientWarningsProvider.php', + 'OCA\\Settings\\AccountWarnings\\QuotaWarning' => $baseDir . '/../lib/AccountWarnings/QuotaWarning.php', + 'OCA\\Settings\\AccountWarnings\\QuotaWarningsProvider' => $baseDir . '/../lib/AccountWarnings/QuotaWarningsProvider.php', 'OCA\\Settings\\Activity\\GroupProvider' => $baseDir . '/../lib/Activity/GroupProvider.php', 'OCA\\Settings\\Activity\\GroupSetting' => $baseDir . '/../lib/Activity/GroupSetting.php', 'OCA\\Settings\\Activity\\Provider' => $baseDir . '/../lib/Activity/Provider.php', diff --git a/apps/settings/composer/composer/autoload_static.php b/apps/settings/composer/composer/autoload_static.php index 4984a706ec8ca..513fa8af6e205 100644 --- a/apps/settings/composer/composer/autoload_static.php +++ b/apps/settings/composer/composer/autoload_static.php @@ -25,6 +25,8 @@ class ComposerStaticInitSettings 'OCA\\Settings\\AccountWarnings\\AccountWarningsManager' => __DIR__ . '/..' . '/../lib/AccountWarnings/AccountWarningsManager.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarning' => __DIR__ . '/..' . '/../lib/AccountWarnings/OutdatedClientWarning.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarningsProvider' => __DIR__ . '/..' . '/../lib/AccountWarnings/OutdatedClientWarningsProvider.php', + 'OCA\\Settings\\AccountWarnings\\QuotaWarning' => __DIR__ . '/..' . '/../lib/AccountWarnings/QuotaWarning.php', + 'OCA\\Settings\\AccountWarnings\\QuotaWarningsProvider' => __DIR__ . '/..' . '/../lib/AccountWarnings/QuotaWarningsProvider.php', 'OCA\\Settings\\Activity\\GroupProvider' => __DIR__ . '/..' . '/../lib/Activity/GroupProvider.php', 'OCA\\Settings\\Activity\\GroupSetting' => __DIR__ . '/..' . '/../lib/Activity/GroupSetting.php', 'OCA\\Settings\\Activity\\Provider' => __DIR__ . '/..' . '/../lib/Activity/Provider.php', diff --git a/apps/settings/lib/AccountWarnings/QuotaWarning.php b/apps/settings/lib/AccountWarnings/QuotaWarning.php new file mode 100644 index 0000000000000..de5351389d6f4 --- /dev/null +++ b/apps/settings/lib/AccountWarnings/QuotaWarning.php @@ -0,0 +1,57 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Settings\AccountWarnings; + +use OCP\Settings\IAccountWarning; +use OCP\IL10N; + +class QuotaWarning implements IAccountWarning { + public const THRESHOLDS = [ + 98 => IAccountWarning::SEVERITY_ERROR, + 90 => IAccountWarning::SEVERITY_WARNING, + 80 => IAccountWarning::SEVERITY_INFO, + ]; + + public function __construct( + private IL10N $l10n, + private int $count, + private int $threshold, + ) { + } + + public function getText(): string { + return $this->l10n->n( + '%n account is using more than %d%% of their quota', + '%n accounts are using more than %d%% of their quota', + $this->count, + [$this->threshold] + ); + } + + public function getSeverity(): string { + return self::THRESHOLDS[$this->threshold]; + } +} diff --git a/apps/settings/lib/AccountWarnings/QuotaWarningsProvider.php b/apps/settings/lib/AccountWarnings/QuotaWarningsProvider.php new file mode 100644 index 0000000000000..d6921aab0fc1d --- /dev/null +++ b/apps/settings/lib/AccountWarnings/QuotaWarningsProvider.php @@ -0,0 +1,75 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Settings\AccountWarnings; + +use OCP\Settings\IAccountWarningsProvider; +use OCP\IL10N; +use OCP\IUserManager; +use OCP\IUser; +use OCP\Files\IRootFolder; + +class QuotaWarningsProvider implements IAccountWarningsProvider { + public function __construct( + private IL10N $l10n, + private IUserManager $userManager, + private IRootFolder $rootFolder, + ) { + } + + public function getName(): string { + return $this->l10n->t('Quota'); + } + + public function getAccountWarnings(): array { + $users = []; + foreach (QuotaWarning::THRESHOLDS as $threshold) { + $users[$threshold] = 0; + } + $this->userManager->callForSeenUsers(function (IUser $user) use (&$users) { + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); + $size = $userFolder->getSize(); + $quota = \OCP\Util::computerFileSize($user->getQuota()); + if ($quota === false) { + return; + } + $usage = 100 * ($size / $quota); + foreach (QuotaWarning::THRESHOLDS as $threshold => $level) { + if ($usage >= $threshold) { + $users[$threshold]++; + break; + } + } + }); + $warnings = []; + foreach ($users as $threshold => $count) { + if ($count > 0) { + $warnings[] = new QuotaWarning($this->l10n, $count, $threshold); + } + } + return $warnings; + } +} diff --git a/apps/settings/lib/AppInfo/Application.php b/apps/settings/lib/AppInfo/Application.php index 50bd64196a720..20515100cb322 100644 --- a/apps/settings/lib/AppInfo/Application.php +++ b/apps/settings/lib/AppInfo/Application.php @@ -38,6 +38,7 @@ use OC\Authentication\Token\IProvider; use OC\Server; use OCA\Settings\AccountWarnings\OutdatedClientWarningsProvider; +use OCA\Settings\AccountWarnings\QuotaWarningsProvider; use OCA\Settings\Hooks; use OCA\Settings\Listener\AppPasswordCreatedActivityListener; use OCA\Settings\Listener\GroupRemovedListener; @@ -139,6 +140,7 @@ public function register(IRegistrationContext $context): void { $context->registerUserMigrator(AccountMigrator::class); $context->registerAccountWarningsProvider(OutdatedClientWarningsProvider::class); + $context->registerAccountWarningsProvider(QuotaWarningsProvider::class); } public function boot(IBootContext $context): void { From 2f96c57f6f3c0a2f6d08747a9d54ee345cf15351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 3 Oct 2023 15:01:13 +0200 Subject: [PATCH 09/11] Add user id information to quota warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a temporary solution, we’ll need to add the list in array format so that the UI can do something nice with it. Signed-off-by: Côme Chilliet --- apps/settings/lib/AccountWarnings/QuotaWarning.php | 10 +++++----- .../lib/AccountWarnings/QuotaWarningsProvider.php | 9 +++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/settings/lib/AccountWarnings/QuotaWarning.php b/apps/settings/lib/AccountWarnings/QuotaWarning.php index de5351389d6f4..8bd40b1e26741 100644 --- a/apps/settings/lib/AccountWarnings/QuotaWarning.php +++ b/apps/settings/lib/AccountWarnings/QuotaWarning.php @@ -37,17 +37,17 @@ class QuotaWarning implements IAccountWarning { public function __construct( private IL10N $l10n, - private int $count, + private array $userIds, private int $threshold, ) { } public function getText(): string { return $this->l10n->n( - '%n account is using more than %d%% of their quota', - '%n accounts are using more than %d%% of their quota', - $this->count, - [$this->threshold] + '%n account is using more than %d%% of their quota: %s', + '%n accounts are using more than %d%% of their quota: %s', + count($this->userIds), + [$this->threshold, implode(',', $this->userIds)] ); } diff --git a/apps/settings/lib/AccountWarnings/QuotaWarningsProvider.php b/apps/settings/lib/AccountWarnings/QuotaWarningsProvider.php index d6921aab0fc1d..518ed0f16cbdf 100644 --- a/apps/settings/lib/AccountWarnings/QuotaWarningsProvider.php +++ b/apps/settings/lib/AccountWarnings/QuotaWarningsProvider.php @@ -47,7 +47,7 @@ public function getName(): string { public function getAccountWarnings(): array { $users = []; foreach (QuotaWarning::THRESHOLDS as $threshold) { - $users[$threshold] = 0; + $users[$threshold] = []; } $this->userManager->callForSeenUsers(function (IUser $user) use (&$users) { $userFolder = $this->rootFolder->getUserFolder($user->getUID()); @@ -59,15 +59,16 @@ public function getAccountWarnings(): array { $usage = 100 * ($size / $quota); foreach (QuotaWarning::THRESHOLDS as $threshold => $level) { if ($usage >= $threshold) { - $users[$threshold]++; + $users[$threshold][] = $user->getUID(); break; } } }); $warnings = []; - foreach ($users as $threshold => $count) { + foreach ($users as $threshold => $uids) { + $count = count($uids); if ($count > 0) { - $warnings[] = new QuotaWarning($this->l10n, $count, $threshold); + $warnings[] = new QuotaWarning($this->l10n, $uids, $threshold); } } return $warnings; From 329850388fc6a22ced4b8e20b1ea3ddad89f285a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Tue, 3 Oct 2023 17:20:53 +0200 Subject: [PATCH 10/11] Add ClientDiagnosticWarningsProvider and fix diagnostic PUT route MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- .../composer/composer/autoload_classmap.php | 2 + .../composer/composer/autoload_static.php | 2 + .../ClientDiagnosticWarning.php | 77 ++++++++++++++++ .../ClientDiagnosticWarningsProvider.php | 88 +++++++++++++++++++ apps/settings/lib/AppInfo/Application.php | 2 + .../ClientDiagnosticsController.php | 34 ++++--- apps/settings/lib/Db/ClientDiagnostic.php | 25 +++++- .../lib/Db/ClientDiagnosticMapper.php | 28 ++++++ .../Version28000Date20231002171502.php | 7 +- 9 files changed, 249 insertions(+), 16 deletions(-) create mode 100644 apps/settings/lib/AccountWarnings/ClientDiagnosticWarning.php create mode 100644 apps/settings/lib/AccountWarnings/ClientDiagnosticWarningsProvider.php diff --git a/apps/settings/composer/composer/autoload_classmap.php b/apps/settings/composer/composer/autoload_classmap.php index 2dc6b4a9f3103..dd0d4bf671179 100644 --- a/apps/settings/composer/composer/autoload_classmap.php +++ b/apps/settings/composer/composer/autoload_classmap.php @@ -8,6 +8,8 @@ return array( 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'OCA\\Settings\\AccountWarnings\\AccountWarningsManager' => $baseDir . '/../lib/AccountWarnings/AccountWarningsManager.php', + 'OCA\\Settings\\AccountWarnings\\ClientDiagnosticWarning' => $baseDir . '/../lib/AccountWarnings/ClientDiagnosticWarning.php', + 'OCA\\Settings\\AccountWarnings\\ClientDiagnosticWarningsProvider' => $baseDir . '/../lib/AccountWarnings/ClientDiagnosticWarningsProvider.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarning' => $baseDir . '/../lib/AccountWarnings/OutdatedClientWarning.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarningsProvider' => $baseDir . '/../lib/AccountWarnings/OutdatedClientWarningsProvider.php', 'OCA\\Settings\\AccountWarnings\\QuotaWarning' => $baseDir . '/../lib/AccountWarnings/QuotaWarning.php', diff --git a/apps/settings/composer/composer/autoload_static.php b/apps/settings/composer/composer/autoload_static.php index 513fa8af6e205..5485e54549a66 100644 --- a/apps/settings/composer/composer/autoload_static.php +++ b/apps/settings/composer/composer/autoload_static.php @@ -23,6 +23,8 @@ class ComposerStaticInitSettings public static $classMap = array ( 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'OCA\\Settings\\AccountWarnings\\AccountWarningsManager' => __DIR__ . '/..' . '/../lib/AccountWarnings/AccountWarningsManager.php', + 'OCA\\Settings\\AccountWarnings\\ClientDiagnosticWarning' => __DIR__ . '/..' . '/../lib/AccountWarnings/ClientDiagnosticWarning.php', + 'OCA\\Settings\\AccountWarnings\\ClientDiagnosticWarningsProvider' => __DIR__ . '/..' . '/../lib/AccountWarnings/ClientDiagnosticWarningsProvider.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarning' => __DIR__ . '/..' . '/../lib/AccountWarnings/OutdatedClientWarning.php', 'OCA\\Settings\\AccountWarnings\\OutdatedClientWarningsProvider' => __DIR__ . '/..' . '/../lib/AccountWarnings/OutdatedClientWarningsProvider.php', 'OCA\\Settings\\AccountWarnings\\QuotaWarning' => __DIR__ . '/..' . '/../lib/AccountWarnings/QuotaWarning.php', diff --git a/apps/settings/lib/AccountWarnings/ClientDiagnosticWarning.php b/apps/settings/lib/AccountWarnings/ClientDiagnosticWarning.php new file mode 100644 index 0000000000000..4cd10e267ffc2 --- /dev/null +++ b/apps/settings/lib/AccountWarnings/ClientDiagnosticWarning.php @@ -0,0 +1,77 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Settings\AccountWarnings; + +use OCA\Settings\Db\ClientDiagnostic; +use OCP\Settings\IAccountWarning; +use OCP\IL10N; + +class ClientDiagnosticWarning implements IAccountWarning { + /** + * @param string $type one of ClientDiagnostic::TYPE_* constants + */ + public function __construct( + private IL10N $l10n, + private string $type, + private int $count, + private string $uid, + private string $clientName, + private int $oldest, + ) { + } + + public function getText(): string { + $oldest = new \DateTime(); + $oldest->setTimestamp($this->oldest); + // TODO check which format to use + $formattedOldest = $oldest->format('Y-m-d H:i:s'); + return match ($this->type) { + ClientDiagnostic::TYPE_CONFLICT => + $this->l10n->n( + 'Account "%s" had %n conflict on client %s on %s', + 'Account "%s" had %n conflicts on client %s, oldest one on %s', + $this->count, + [$this->uid, $this->clientName, $formattedOldest] + ), + ClientDiagnostic::TYPE_FAILED_UPLOAD => + $this->l10n->n( + 'Account %s had %n failed upload on client %s on %s', + 'Account %s had %n failed uploads on client %s, oldest one on %s', + $this->count, + [$this->uid, $this->clientName, $formattedOldest] + ), + default => 'Unknown problem', + }; + } + + public function getSeverity(): string { + return match ($this->type) { + ClientDiagnostic::TYPE_CONFLICT => IAccountWarning::SEVERITY_WARNING, + ClientDiagnostic::TYPE_FAILED_UPLOAD => IAccountWarning::SEVERITY_WARNING, + default => IAccountWarning::SEVERITY_ERROR, + }; + } +} diff --git a/apps/settings/lib/AccountWarnings/ClientDiagnosticWarningsProvider.php b/apps/settings/lib/AccountWarnings/ClientDiagnosticWarningsProvider.php new file mode 100644 index 0000000000000..c895600736bcb --- /dev/null +++ b/apps/settings/lib/AccountWarnings/ClientDiagnosticWarningsProvider.php @@ -0,0 +1,88 @@ + + * + * @author Côme Chilliet + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Settings\AccountWarnings; + +use OCA\Settings\Db\ClientDiagnostic; +use OCA\Settings\Db\ClientDiagnosticMapper; +use OCP\Settings\IAccountWarningsProvider; +use OC\Authentication\Token\IToken; +use OC\Authentication\Token\IProvider; +use OCP\IL10N; +use OCP\IUserManager; + +class ClientDiagnosticWarningsProvider implements IAccountWarningsProvider { + /** + * Maximum age for a client diagnostic to be considered still valid, in seconds + * Diagnostic timestamp will be compared to last check of the associated authtoken + */ + public const MAX_AGE = 24 * 60 * 60; + + public function __construct( + private IL10N $l10n, + private IUserManager $userManager, + private ClientDiagnosticMapper $diagnosticMapper, + private IProvider $tokenProvider, + ) { + } + + public function getName(): string { + return $this->l10n->t('Client errors'); + } + + public function getAccountWarnings(): array { + $diagnostics = $this->diagnosticMapper->getAll(); + + $warnings = []; + foreach ($diagnostics as $diagnostic) { + $token = $this->getAuthtoken($diagnostic); + // if (!$this->isRecentEnough($diagnostic, $token)) { + // // TODO delete diagnostic? + // continue; + // } + $data = $diagnostic->getDiagnosticAsArray(); + foreach ($data['problems'] as $type => $problemDetails) { + $warnings[] = new ClientDiagnosticWarning( + $this->l10n, + $type, + $problemDetails['count'], + $token->getUID(), + $token->getName(), + $problemDetails['oldest'] + ); + } + } + return $warnings; + } + + private function getAuthtoken(ClientDiagnostic $diagnostic): IToken { + return $this->tokenProvider->getTokenById($diagnostic->getAuthtokenid()); + } + + private function isRecentEnough(ClientDiagnostic $diagnostic, IToken $token): bool { + return ($diagnostic->getTimestamp()->getTimestamp() >= $token->getLastCheck() + self::MAX_AGE); + } +} diff --git a/apps/settings/lib/AppInfo/Application.php b/apps/settings/lib/AppInfo/Application.php index 20515100cb322..320a7e245d28e 100644 --- a/apps/settings/lib/AppInfo/Application.php +++ b/apps/settings/lib/AppInfo/Application.php @@ -37,6 +37,7 @@ use OC\Authentication\Events\AppPasswordCreatedEvent; use OC\Authentication\Token\IProvider; use OC\Server; +use OCA\Settings\AccountWarnings\ClientDiagnosticWarningsProvider; use OCA\Settings\AccountWarnings\OutdatedClientWarningsProvider; use OCA\Settings\AccountWarnings\QuotaWarningsProvider; use OCA\Settings\Hooks; @@ -139,6 +140,7 @@ public function register(IRegistrationContext $context): void { $context->registerUserMigrator(AccountMigrator::class); + $context->registerAccountWarningsProvider(ClientDiagnosticWarningsProvider::class); $context->registerAccountWarningsProvider(OutdatedClientWarningsProvider::class); $context->registerAccountWarningsProvider(QuotaWarningsProvider::class); } diff --git a/apps/settings/lib/Controller/ClientDiagnosticsController.php b/apps/settings/lib/Controller/ClientDiagnosticsController.php index 08508722896e7..76b797bd5a1c7 100644 --- a/apps/settings/lib/Controller/ClientDiagnosticsController.php +++ b/apps/settings/lib/Controller/ClientDiagnosticsController.php @@ -25,19 +25,21 @@ namespace OCA\Settings\Controller; -use OC\Authentication\Exceptions\InvalidTokenException; -use OC\Authentication\Token\IProvider; use OCA\Settings\Db\ClientDiagnostic; use OCA\Settings\Db\ClientDiagnosticMapper; -use OCP\AppFramework\Controller; +use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCSController; use OCP\IRequest; use OCP\ISession; use OCP\IUserSession; use OCP\Session\Exceptions\SessionNotAvailableException; +use OC\Authentication\Exceptions\InvalidTokenException; +use OC\Authentication\Token\IProvider; +use Psr\Clock\ClockInterface; -class ClientDiagnosticsController extends Controller { +class ClientDiagnosticsController extends OCSController { public function __construct( string $appName, IRequest $request, @@ -45,6 +47,7 @@ public function __construct( private IUserSession $userSession, private ClientDiagnosticMapper $mapper, private IProvider $tokenProvider, + private ClockInterface $clock, ) { parent::__construct($appName, $request); } @@ -52,8 +55,9 @@ public function __construct( /** * @NoAdminRequired * @NoSubAdminRequired + * @NoCSRFRequired */ - public function update(array $data): DataResponse { + public function update(array $problems): DataResponse { try { $sessionId = $this->session->getId(); } catch (SessionNotAvailableException $e) { @@ -71,13 +75,21 @@ public function update(array $data): DataResponse { return new DataResponse([], Http::STATUS_METHOD_NOT_ALLOWED); } - /* TODO: validate data structure */ + /* TODO: validate problems structure */ - $entity = $this->mapper->insertOrUpdate( - ClientDiagnostic::fromParams([ - 'authtokenid' => $token->getId(), - 'diagnostic' => json_encode($data), - ])); + try { + $entity = $this->mapper->findByAuthtokenid($token->getId()); + $entity->setDiagnostic(json_encode(['problems' => $problems], JSON_THROW_ON_ERROR)); + $entity->setTimestamp(\DateTime::createFromImmutable($this->clock->now())); + $this->mapper->update($entity); + } catch (DoesNotExistException $e) { + $entity = $this->mapper->insert( + ClientDiagnostic::fromParams([ + 'authtokenid' => $token->getId(), + 'diagnostic' => json_encode(['problems' => $problems], JSON_THROW_ON_ERROR), + 'timestamp' => \DateTime::createFromImmutable($this->clock->now()), + ])); + } return new DataResponse([]); } diff --git a/apps/settings/lib/Db/ClientDiagnostic.php b/apps/settings/lib/Db/ClientDiagnostic.php index df86fddd4ec2a..339522b678958 100644 --- a/apps/settings/lib/Db/ClientDiagnostic.php +++ b/apps/settings/lib/Db/ClientDiagnostic.php @@ -27,21 +27,40 @@ namespace OCA\Settings\Db; use OCP\AppFramework\Db\Entity; -use OCP\DB\Types; /** * @method void setAuthtokenid(int $authtokenid) * @method int getAuthtokenid() + * @method void setDiagnostic(string $diagnostic) + * @method string getDiagnostic() + * @method \DateTime getTimestamp() + * @method void setTimestamp(\DateTime $timestamp) */ class ClientDiagnostic extends Entity { + public const TYPE_CONFLICT = 'conflict'; + public const TYPE_FAILED_UPLOAD = 'failed-upload'; + public const TYPES = [ + self::TYPE_CONFLICT, + self::TYPE_FAILED_UPLOAD, + ]; + /** @var int */ protected $authtokenid; /** @var string json-encoded*/ protected $diagnostic; + /** @var \DateTime */ + public $timestamp; + public function __construct() { - $this->addType('authtokenid', Types::BIGINT); - $this->addType('diagnostic', Types::TEXT); + $this->addType('authtokenid', 'int'); + $this->addType('diagnostic', 'string'); + $this->addType('timestamp', 'datetime'); + } + + public function getDiagnosticAsArray(): array { + $data = json_decode($this->diagnostic, true, JSON_THROW_ON_ERROR); + return $data; } } diff --git a/apps/settings/lib/Db/ClientDiagnosticMapper.php b/apps/settings/lib/Db/ClientDiagnosticMapper.php index 79b1f72c4ae8c..2d881804af63d 100644 --- a/apps/settings/lib/Db/ClientDiagnosticMapper.php +++ b/apps/settings/lib/Db/ClientDiagnosticMapper.php @@ -26,6 +26,7 @@ namespace OCA\Settings\Db; +use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\QBMapper; use OCP\IDBConnection; @@ -38,4 +39,31 @@ class ClientDiagnosticMapper extends QBMapper { public function __construct(IDBConnection $db) { parent::__construct($db, self::TABLE_NAME, ClientDiagnostic::class); } + + /** + * @return ClientDiagnostic[] + */ + public function getAll(): array { + $qb = $this->db->getQueryBuilder(); + + $select = $qb + ->select('*') + ->from($this->getTableName()); + + return $this->findEntities($select); + } + + /** + * @throws DoesNotExistException + */ + public function findByAuthtokenid(int $id): ClientDiagnostic { + $qb = $this->db->getQueryBuilder(); + + $select = $qb + ->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq('authtokenid', $qb->createNamedParameter($id, $qb::PARAM_INT))); + + return $this->findEntity($select); + } } diff --git a/core/Migrations/Version28000Date20231002171502.php b/core/Migrations/Version28000Date20231002171502.php index 1de7b9ee2d75d..70860730d9dd6 100644 --- a/core/Migrations/Version28000Date20231002171502.php +++ b/core/Migrations/Version28000Date20231002171502.php @@ -59,9 +59,12 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt $table->addColumn('diagnostic', Types::TEXT, [ 'notnull' => true, ]); + $table->addColumn('timestamp', Types::DATETIME, [ + 'notnull' => true, + ]); - $table->setPrimaryKey(['id'], 'client_diagnostics_id_primary'); - $table->addUniqueIndex(['authtokenid'], 'client_diagnostics_authtokenid_index'); + $table->setPrimaryKey(['id'], 'client_diag_id_primary'); + $table->addUniqueIndex(['authtokenid'], 'client_diag_authtokenid_index'); $changed = true; return $schema; From 0cde8b9eea6bea83657aa27bdcc7aeca5bc8cc93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Thu, 5 Oct 2023 11:11:55 +0200 Subject: [PATCH 11/11] Move the route for pushing diagnostics to ocs endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- apps/settings/appinfo/routes.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/settings/appinfo/routes.php b/apps/settings/appinfo/routes.php index 48f9fd8a0a639..6b7cc634fc208 100644 --- a/apps/settings/appinfo/routes.php +++ b/apps/settings/appinfo/routes.php @@ -36,7 +36,6 @@ ['name' => 'AuthorizedGroup#destroy', 'url' => '/settings/authorizedgroups', 'verb' => 'DELETE'], ['name' => 'AuthSettings#wipe', 'url' => '/settings/personal/authtokens/wipe/{id}', 'verb' => 'POST' , 'root' => ''], - ['name' => 'ClientDiagnostics#update', 'url' => '/settings/diagnostics', 'verb' => 'PUT' , 'root' => ''], ['name' => 'AccountWarnings#getAll', 'url' => '/settings/accountwarnings', 'verb' => 'GET' , 'root' => ''], ['name' => 'MailSettings#setMailSettings', 'url' => '/settings/admin/mailsettings', 'verb' => 'POST' , 'root' => ''], @@ -86,5 +85,8 @@ ['name' => 'WebAuthn#deleteRegistration', 'url' => '/settings/api/personal/webauthn/registration/{id}', 'verb' => 'DELETE' , 'root' => ''], ['name' => 'Reasons#getPdf', 'url' => '/settings/download/reasons', 'verb' => 'GET', 'root' => ''], - ] + ], + 'ocs' => [ + ['name' => 'ClientDiagnostics#update', 'url' => '/diagnostics', 'verb' => 'PUT' ], + ], ];