diff --git a/apps/encryption/js/encryption.js b/apps/encryption/js/encryption.js deleted file mode 100644 index 3e528e8c18b..00000000000 --- a/apps/encryption/js/encryption.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2014-2015 ownCloud, Inc. - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -/** - * @namespace OC - */ -OC.Encryption = _.extend(OC.Encryption || {}, { - displayEncryptionWarning: function() { - if (!OC.currentUser || !OC.Notification.isHidden()) { - return - } - - $.get( - OC.generateUrl('/apps/encryption/ajax/getStatus'), - function(result) { - if (result.status === 'interactionNeeded') { - OC.Notification.show(result.data.message) - } - }, - ) - }, -}) -window.addEventListener('DOMContentLoaded', function() { - // wait for other apps/extensions to register their event handlers and file actions - // in the "ready" clause - _.defer(function() { - OC.Encryption.displayEncryptionWarning() - }) -}) diff --git a/apps/encryption/js/settings-admin.js b/apps/encryption/js/settings-admin.js deleted file mode 100644 index dd0c1823ede..00000000000 --- a/apps/encryption/js/settings-admin.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2013-2015 ownCloud, Inc. - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -window.addEventListener('DOMContentLoaded', function() { - $('input:button[name="enableRecoveryKey"]').click(function() { - const recoveryStatus = $(this).attr('status') - const newRecoveryStatus = (1 + parseInt(recoveryStatus)) % 2 - const buttonValue = $(this).attr('value') - - const recoveryPassword = $('#encryptionRecoveryPassword').val() - const confirmPassword = $('#repeatEncryptionRecoveryPassword').val() - OC.msg.startSaving('#encryptionSetRecoveryKey .msg') - $.post( - OC.generateUrl('/apps/encryption/ajax/adminRecovery'), - { - adminEnableRecovery: newRecoveryStatus, - recoveryPassword, - confirmPassword, - }, - ).done(function(data) { - OC.msg.finishedSuccess('#encryptionSetRecoveryKey .msg', data.data.message) - - if (newRecoveryStatus === 0) { - $('p[name="changeRecoveryPasswordBlock"]').addClass('hidden') - $('input:button[name="enableRecoveryKey"]').attr('value', 'Enable recovery key') - $('input:button[name="enableRecoveryKey"]').attr('status', '0') - } else { - $('input:password[name="changeRecoveryPassword"]').val('') - $('p[name="changeRecoveryPasswordBlock"]').removeClass('hidden') - $('input:button[name="enableRecoveryKey"]').attr('value', 'Disable recovery key') - $('input:button[name="enableRecoveryKey"]').attr('status', '1') - } - }) - .fail(function(jqXHR) { - $('input:button[name="enableRecoveryKey"]').attr('value', buttonValue) - $('input:button[name="enableRecoveryKey"]').attr('status', recoveryStatus) - OC.msg.finishedError('#encryptionSetRecoveryKey .msg', JSON.parse(jqXHR.responseText).data.message) - }) - }) - - $('#repeatEncryptionRecoveryPassword').keyup(function(event) { - if (event.keyCode == 13) { - $('#enableRecoveryKey').click() - } - }) - - // change recovery password - - $('button:button[name="submitChangeRecoveryKey"]').click(function() { - const oldRecoveryPassword = $('#oldEncryptionRecoveryPassword').val() - const newRecoveryPassword = $('#newEncryptionRecoveryPassword').val() - const confirmNewPassword = $('#repeatedNewEncryptionRecoveryPassword').val() - OC.msg.startSaving('#encryptionChangeRecoveryKey .msg') - $.post( - OC.generateUrl('/apps/encryption/ajax/changeRecoveryPassword'), - { - oldPassword: oldRecoveryPassword, - newPassword: newRecoveryPassword, - confirmPassword: confirmNewPassword, - }, - ).done(function(data) { - OC.msg.finishedSuccess('#encryptionChangeRecoveryKey .msg', data.data.message) - }) - .fail(function(jqXHR) { - OC.msg.finishedError('#encryptionChangeRecoveryKey .msg', JSON.parse(jqXHR.responseText).data.message) - }) - }) - - $('#encryptHomeStorage').change(function() { - $.post( - OC.generateUrl('/apps/encryption/ajax/setEncryptHomeStorage'), - { - encryptHomeStorage: this.checked, - }, - ) - }) -}) diff --git a/apps/encryption/js/settings-personal.js b/apps/encryption/js/settings-personal.js deleted file mode 100644 index 76560afab58..00000000000 --- a/apps/encryption/js/settings-personal.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2013-2015 ownCloud, Inc. - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -OC.Encryption = _.extend(OC.Encryption || {}, { - updatePrivateKeyPassword: function() { - const oldPrivateKeyPassword = $('input:password[id="oldPrivateKeyPassword"]').val() - const newPrivateKeyPassword = $('input:password[id="newPrivateKeyPassword"]').val() - OC.msg.startSaving('#ocDefaultEncryptionModule .msg') - $.post( - OC.generateUrl('/apps/encryption/ajax/updatePrivateKeyPassword'), - { - oldPassword: oldPrivateKeyPassword, - newPassword: newPrivateKeyPassword, - }, - ).done(function(data) { - OC.msg.finishedSuccess('#ocDefaultEncryptionModule .msg', data.message) - }).fail(function(jqXHR) { - OC.msg.finishedError('#ocDefaultEncryptionModule .msg', JSON.parse(jqXHR.responseText).message) - }) - }, -}) - -window.addEventListener('DOMContentLoaded', function() { - // Trigger ajax on recoveryAdmin status change - $('input:radio[name="userEnableRecovery"]').change(function() { - const recoveryStatus = $(this).val() - OC.msg.startAction('#userEnableRecovery .msg', 'Updating recovery keys. This can take some time...') - $.post( - OC.generateUrl('/apps/encryption/ajax/userSetRecovery'), - { - userEnableRecovery: recoveryStatus, - }, - ).done(function(data) { - OC.msg.finishedSuccess('#userEnableRecovery .msg', data.data.message) - }) - .fail(function(jqXHR) { - OC.msg.finishedError('#userEnableRecovery .msg', JSON.parse(jqXHR.responseText).data.message) - }) - // Ensure page is not reloaded on form submit - return false - }) - - // update private key password - - $('input:password[name="changePrivateKeyPassword"]').keyup(function(event) { - const oldPrivateKeyPassword = $('input:password[id="oldPrivateKeyPassword"]').val() - const newPrivateKeyPassword = $('input:password[id="newPrivateKeyPassword"]').val() - if (newPrivateKeyPassword !== '' && oldPrivateKeyPassword !== '') { - $('button:button[name="submitChangePrivateKeyPassword"]').removeAttr('disabled') - if (event.which === 13) { - OC.Encryption.updatePrivateKeyPassword() - } - } else { - $('button:button[name="submitChangePrivateKeyPassword"]').attr('disabled', 'true') - } - }) - - $('button:button[name="submitChangePrivateKeyPassword"]').click(function() { - OC.Encryption.updatePrivateKeyPassword() - }) -}) diff --git a/apps/encryption/lib/Controller/RecoveryController.php b/apps/encryption/lib/Controller/RecoveryController.php index e7fb6bafb67..cc172d18b30 100644 --- a/apps/encryption/lib/Controller/RecoveryController.php +++ b/apps/encryption/lib/Controller/RecoveryController.php @@ -12,35 +12,23 @@ use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; -use OCP\IConfig; +use OCP\Encryption\Exceptions\GenericEncryptionException; use OCP\IL10N; use OCP\IRequest; +use Psr\Log\LoggerInterface; class RecoveryController extends Controller { - /** - * @param string $AppName - * @param IRequest $request - * @param IConfig $config - * @param IL10N $l - * @param Recovery $recovery - */ public function __construct( - $appName, + string $appName, IRequest $request, - private IConfig $config, private IL10N $l, private Recovery $recovery, + private LoggerInterface $logger, ) { parent::__construct($appName, $request); } - /** - * @param string $recoveryPassword - * @param string $confirmPassword - * @param string $adminEnableRecovery - * @return DataResponse - */ - public function adminRecovery($recoveryPassword, $confirmPassword, $adminEnableRecovery) { + public function adminRecovery(string $recoveryPassword, string $confirmPassword, bool $adminEnableRecovery): DataResponse { // Check if both passwords are the same if (empty($recoveryPassword)) { $errorMessage = $this->l->t('Missing recovery key password'); @@ -60,28 +48,28 @@ class RecoveryController extends Controller { Http::STATUS_BAD_REQUEST); } - if (isset($adminEnableRecovery) && $adminEnableRecovery === '1') { - if ($this->recovery->enableAdminRecovery($recoveryPassword)) { - return new DataResponse(['data' => ['message' => $this->l->t('Recovery key successfully enabled')]]); + try { + if ($adminEnableRecovery) { + if ($this->recovery->enableAdminRecovery($recoveryPassword)) { + return new DataResponse(['data' => ['message' => $this->l->t('Recovery key successfully enabled')]]); + } + return new DataResponse(['data' => ['message' => $this->l->t('Could not enable recovery key. Please check your recovery key password!')]], Http::STATUS_BAD_REQUEST); + } else { + if ($this->recovery->disableAdminRecovery($recoveryPassword)) { + return new DataResponse(['data' => ['message' => $this->l->t('Recovery key successfully disabled')]]); + } + return new DataResponse(['data' => ['message' => $this->l->t('Could not disable recovery key. Please check your recovery key password!')]], Http::STATUS_BAD_REQUEST); } - return new DataResponse(['data' => ['message' => $this->l->t('Could not enable recovery key. Please check your recovery key password!')]], Http::STATUS_BAD_REQUEST); - } elseif (isset($adminEnableRecovery) && $adminEnableRecovery === '0') { - if ($this->recovery->disableAdminRecovery($recoveryPassword)) { - return new DataResponse(['data' => ['message' => $this->l->t('Recovery key successfully disabled')]]); + } catch (\Exception $e) { + $this->logger->error('Error enabling or disabling recovery key', ['exception' => $e]); + if ($e instanceof GenericEncryptionException) { + return new DataResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR); } - return new DataResponse(['data' => ['message' => $this->l->t('Could not disable recovery key. Please check your recovery key password!')]], Http::STATUS_BAD_REQUEST); + return new DataResponse([], Http::STATUS_INTERNAL_SERVER_ERROR); } - // this response should never be sent but just in case. - return new DataResponse(['data' => ['message' => $this->l->t('Missing parameters')]], Http::STATUS_BAD_REQUEST); } - /** - * @param string $newPassword - * @param string $oldPassword - * @param string $confirmPassword - * @return DataResponse - */ - public function changeRecoveryPassword($newPassword, $oldPassword, $confirmPassword) { + public function changeRecoveryPassword(string $newPassword, string $oldPassword, string $confirmPassword): DataResponse { //check if both passwords are the same if (empty($oldPassword)) { $errorMessage = $this->l->t('Please provide the old recovery password'); @@ -103,23 +91,30 @@ class RecoveryController extends Controller { return new DataResponse(['data' => ['message' => $errorMessage]], Http::STATUS_BAD_REQUEST); } - $result = $this->recovery->changeRecoveryKeyPassword($newPassword, - $oldPassword); + try { + $result = $this->recovery->changeRecoveryKeyPassword($newPassword, + $oldPassword); - if ($result) { - return new DataResponse( - [ - 'data' => [ - 'message' => $this->l->t('Password successfully changed.')] - ] - ); - } - return new DataResponse( - [ + if ($result) { + return new DataResponse( + [ + 'data' => [ + 'message' => $this->l->t('Password successfully changed.')] + ] + ); + } + return new DataResponse([ 'data' => [ 'message' => $this->l->t('Could not change the password. Maybe the old password was not correct.') ] ], Http::STATUS_BAD_REQUEST); + } catch (\Exception $e) { + $this->logger->error('Error changing recovery password', ['exception' => $e]); + if ($e instanceof GenericEncryptionException) { + return new DataResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR); + } + return new DataResponse([], Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** diff --git a/apps/encryption/lib/Controller/StatusController.php b/apps/encryption/lib/Controller/StatusController.php index 914432f78a3..582401502a1 100644 --- a/apps/encryption/lib/Controller/StatusController.php +++ b/apps/encryption/lib/Controller/StatusController.php @@ -68,8 +68,10 @@ class StatusController extends Controller { return new DataResponse( [ 'status' => $status, + 'initStatus' => $this->session->getStatus(), 'data' => [ - 'message' => $message] + 'message' => $message, + ], ] ); } diff --git a/apps/encryption/lib/Settings/Admin.php b/apps/encryption/lib/Settings/Admin.php index a5de4ba68ff..1ac2ab5ff5e 100644 --- a/apps/encryption/lib/Settings/Admin.php +++ b/apps/encryption/lib/Settings/Admin.php @@ -7,10 +7,13 @@ namespace OCA\Encryption\Settings; use OC\Files\View; +use OCA\Encryption\AppInfo\Application; use OCA\Encryption\Crypto\Crypt; use OCA\Encryption\Session; use OCA\Encryption\Util; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; +use OCP\IAppConfig; use OCP\IConfig; use OCP\IL10N; use OCP\ISession; @@ -27,6 +30,8 @@ class Admin implements ISettings { private IConfig $config, private IUserManager $userManager, private ISession $session, + private IInitialState $initialState, + private IAppConfig $appConfig, ) { } @@ -48,19 +53,21 @@ class Admin implements ISettings { $this->userManager); // Check if an adminRecovery account is enabled for recovering files after lost pwd - $recoveryAdminEnabled = $this->config->getAppValue('encryption', 'recoveryAdminEnabled', '0'); + $recoveryAdminEnabled = $this->appConfig->getValueBool('encryption', 'recoveryAdminEnabled'); $session = new Session($this->session); $encryptHomeStorage = $util->shouldEncryptHomeStorage(); - $parameters = [ + $this->initialState->provideInitialState('adminSettings', [ 'recoveryEnabled' => $recoveryAdminEnabled, 'initStatus' => $session->getStatus(), 'encryptHomeStorage' => $encryptHomeStorage, 'masterKeyEnabled' => $util->isMasterKeyEnabled(), - ]; + ]); - return new TemplateResponse('encryption', 'settings-admin', $parameters, ''); + \OCP\Util::addStyle(Application::APP_ID, 'settings_admin'); + \OCP\Util::addScript(Application::APP_ID, 'settings_admin'); + return new TemplateResponse(Application::APP_ID, 'settings', renderAs: ''); } /** diff --git a/apps/encryption/lib/Settings/Personal.php b/apps/encryption/lib/Settings/Personal.php index 8814d3afb58..cac6ff249eb 100644 --- a/apps/encryption/lib/Settings/Personal.php +++ b/apps/encryption/lib/Settings/Personal.php @@ -6,20 +6,25 @@ */ namespace OCA\Encryption\Settings; +use OCA\Encryption\AppInfo\Application; use OCA\Encryption\Session; use OCA\Encryption\Util; use OCP\AppFramework\Http\TemplateResponse; -use OCP\IConfig; +use OCP\AppFramework\Services\IInitialState; +use OCP\Encryption\IManager; +use OCP\IAppConfig; use OCP\IUserSession; use OCP\Settings\ISettings; class Personal implements ISettings { public function __construct( - private IConfig $config, private Session $session, private Util $util, private IUserSession $userSession, + private IInitialState $initialState, + private IAppConfig $appConfig, + private IManager $manager, ) { } @@ -28,7 +33,7 @@ class Personal implements ISettings { * @since 9.1 */ public function getForm() { - $recoveryAdminEnabled = $this->config->getAppValue('encryption', 'recoveryAdminEnabled'); + $recoveryAdminEnabled = $this->appConfig->getValueBool('encryption', 'recoveryAdminEnabled'); $privateKeySet = $this->session->isPrivateKeySet(); if (!$recoveryAdminEnabled && $privateKeySet) { @@ -38,20 +43,23 @@ class Personal implements ISettings { $userId = $this->userSession->getUser()->getUID(); $recoveryEnabledForUser = $this->util->isRecoveryEnabledForUser($userId); - $parameters = [ + $this->initialState->provideInitialState('personalSettings', [ 'recoveryEnabled' => $recoveryAdminEnabled, 'recoveryEnabledForUser' => $recoveryEnabledForUser, 'privateKeySet' => $privateKeySet, 'initialized' => $this->session->getStatus(), - ]; - return new TemplateResponse('encryption', 'settings-personal', $parameters, ''); + ]); + + \OCP\Util::addStyle(Application::APP_ID, 'settings_personal'); + \OCP\Util::addScript(Application::APP_ID, 'settings_personal'); + return new TemplateResponse(Application::APP_ID, 'settings', renderAs: ''); } - /** - * @return string the section ID, e.g. 'sharing' - * @since 9.1 - */ public function getSection() { + if (!$this->manager->isEnabled()) { + return null; + } + return 'security'; } diff --git a/apps/encryption/src/components/SettingsAdminHomeStorage.vue b/apps/encryption/src/components/SettingsAdminHomeStorage.vue new file mode 100644 index 00000000000..3c2a9a9ceb5 --- /dev/null +++ b/apps/encryption/src/components/SettingsAdminHomeStorage.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/apps/encryption/src/components/SettingsAdminRecoveryKey.vue b/apps/encryption/src/components/SettingsAdminRecoveryKey.vue new file mode 100644 index 00000000000..f53bf368650 --- /dev/null +++ b/apps/encryption/src/components/SettingsAdminRecoveryKey.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/apps/encryption/src/components/SettingsAdminRecoveryKeyChange.vue b/apps/encryption/src/components/SettingsAdminRecoveryKeyChange.vue new file mode 100644 index 00000000000..e4e1fcbfc62 --- /dev/null +++ b/apps/encryption/src/components/SettingsAdminRecoveryKeyChange.vue @@ -0,0 +1,98 @@ + + + + + + + diff --git a/apps/encryption/src/components/SettingsPersonalChangePrivateKey.vue b/apps/encryption/src/components/SettingsPersonalChangePrivateKey.vue new file mode 100644 index 00000000000..6631b17d12f --- /dev/null +++ b/apps/encryption/src/components/SettingsPersonalChangePrivateKey.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/apps/encryption/src/components/SettingsPersonalEnableRecovery.vue b/apps/encryption/src/components/SettingsPersonalEnableRecovery.vue new file mode 100644 index 00000000000..b3aacd4fece --- /dev/null +++ b/apps/encryption/src/components/SettingsPersonalEnableRecovery.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/apps/encryption/src/encryption.ts b/apps/encryption/src/encryption.ts new file mode 100644 index 00000000000..40eeb65e00e --- /dev/null +++ b/apps/encryption/src/encryption.ts @@ -0,0 +1,21 @@ +/*! + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { getCurrentUser } from '@nextcloud/auth' +import axios from '@nextcloud/axios' +import { showWarning } from '@nextcloud/dialogs' +import { generateUrl } from '@nextcloud/router' + +window.addEventListener('DOMContentLoaded', async function() { + if (getCurrentUser() === null) { + // skip for public pages + return + } + + const { data } = await axios.get(generateUrl('/apps/encryption/ajax/getStatus')) + if (data.status === 'interactionNeeded') { + showWarning(data.data.message) + } +}) diff --git a/apps/encryption/src/settings-admin.ts b/apps/encryption/src/settings-admin.ts new file mode 100644 index 00000000000..66cdc50de94 --- /dev/null +++ b/apps/encryption/src/settings-admin.ts @@ -0,0 +1,10 @@ +/*! + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { createApp } from 'vue' +import SettingsAdmin from './views/SettingsAdmin.vue' + +const app = createApp(SettingsAdmin) +app.mount('#encryption-settings-section') diff --git a/apps/encryption/src/settings-personal.ts b/apps/encryption/src/settings-personal.ts new file mode 100644 index 00000000000..24d9c17fea9 --- /dev/null +++ b/apps/encryption/src/settings-personal.ts @@ -0,0 +1,10 @@ +/*! + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { createApp } from 'vue' +import SettingsPersonal from './views/SettingsPersonal.vue' + +const app = createApp(SettingsPersonal) +app.mount('#encryption-settings-section') diff --git a/apps/encryption/src/utils/logger.ts b/apps/encryption/src/utils/logger.ts new file mode 100644 index 00000000000..2ea1a9c08fe --- /dev/null +++ b/apps/encryption/src/utils/logger.ts @@ -0,0 +1,10 @@ +/*! + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { getLoggerBuilder } from '@nextcloud/logger' + +export const logger = getLoggerBuilder() + .setApp('encryption') + .build() diff --git a/apps/encryption/src/utils/types.ts b/apps/encryption/src/utils/types.ts new file mode 100644 index 00000000000..661c10c6bd5 --- /dev/null +++ b/apps/encryption/src/utils/types.ts @@ -0,0 +1,10 @@ +/*! + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +export const InitStatus = Object.freeze({ + NotInitialized: '0', + InitExecuted: '1', + InitSuccessful: '2', +}) diff --git a/apps/encryption/src/views/SettingsAdmin.vue b/apps/encryption/src/views/SettingsAdmin.vue new file mode 100644 index 00000000000..b1c37325334 --- /dev/null +++ b/apps/encryption/src/views/SettingsAdmin.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/apps/encryption/src/views/SettingsPersonal.vue b/apps/encryption/src/views/SettingsPersonal.vue new file mode 100644 index 00000000000..79a87b8098a --- /dev/null +++ b/apps/encryption/src/views/SettingsPersonal.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/apps/encryption/templates/settings-admin.php b/apps/encryption/templates/settings-admin.php deleted file mode 100644 index 432ba2f11b0..00000000000 --- a/apps/encryption/templates/settings-admin.php +++ /dev/null @@ -1,83 +0,0 @@ - -
-

t('Default encryption module')); ?>

- - t('Encryption app is enabled but your keys are not initialized, please log-out and log-in again')); ?> - -

- /> -
- t('Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted')); ?> -

-
- -

- t('Enable recovery key')) : p($l->t('Disable recovery key')); ?> - -
- - t('The recovery key is an additional encryption key used to encrypt files. It is used to recover files from an account if the password is forgotten.')) ?> - -
- - - -

-

- -

> - t('Change recovery key password:')); ?> - -
- -
- - - - -

- - -
diff --git a/apps/encryption/templates/settings-personal.php b/apps/encryption/templates/settings-personal.php deleted file mode 100644 index 604bed53a8f..00000000000 --- a/apps/encryption/templates/settings-personal.php +++ /dev/null @@ -1,79 +0,0 @@ - -
-

t('Basic encryption module')); ?>

- - - - t('Encryption App is enabled, but your keys are not initialized. Please log-out and log-in again.')); ?> - - -

- - -
- t('Set your old private key password to your current log-in password:')); ?> - t('If you do not remember your old password you can ask your administrator to recover your files.')); - endif; ?> -
- - -
- - -
- - -

- - -
-

- - -
- t('Enabling this option will allow you to reobtain access to your encrypted files in case of password loss')); ?> -
- /> - -
- - /> - -

- - diff --git a/apps/encryption/templates/settings.php b/apps/encryption/templates/settings.php new file mode 100644 index 00000000000..013a8120cce --- /dev/null +++ b/apps/encryption/templates/settings.php @@ -0,0 +1,10 @@ + + +
diff --git a/apps/encryption/tests/Controller/RecoveryControllerTest.php b/apps/encryption/tests/Controller/RecoveryControllerTest.php index 717e31cf53b..242abe8861f 100644 --- a/apps/encryption/tests/Controller/RecoveryControllerTest.php +++ b/apps/encryption/tests/Controller/RecoveryControllerTest.php @@ -16,6 +16,7 @@ use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; class RecoveryControllerTest extends TestCase { @@ -28,11 +29,11 @@ class RecoveryControllerTest extends TestCase { public static function adminRecoveryProvider(): array { return [ - ['test', 'test', '1', 'Recovery key successfully enabled', Http::STATUS_OK], - ['', 'test', '1', 'Missing recovery key password', Http::STATUS_BAD_REQUEST], - ['test', '', '1', 'Please repeat the recovery key password', Http::STATUS_BAD_REQUEST], - ['test', 'something that doesn\'t match', '1', 'Repeated recovery key password does not match the provided recovery key password', Http::STATUS_BAD_REQUEST], - ['test', 'test', '0', 'Recovery key successfully disabled', Http::STATUS_OK], + ['test', 'test', true, 'Recovery key successfully enabled', Http::STATUS_OK], + ['', 'test', true, 'Missing recovery key password', Http::STATUS_BAD_REQUEST], + ['test', '', true, 'Please repeat the recovery key password', Http::STATUS_BAD_REQUEST], + ['test', 'something that doesn\'t match', true, 'Repeated recovery key password does not match the provided recovery key password', Http::STATUS_BAD_REQUEST], + ['test', 'test', false, 'Recovery key successfully disabled', Http::STATUS_OK], ]; } @@ -150,10 +151,12 @@ class RecoveryControllerTest extends TestCase { ->disableOriginalConstructor() ->getMock(); - $this->controller = new RecoveryController('encryption', + $this->controller = new RecoveryController( + 'encryption', $this->requestMock, - $this->configMock, $this->l10nMock, - $this->recoveryMock); + $this->recoveryMock, + $this->createMock(LoggerInterface::class), + ); } } diff --git a/apps/encryption/tests/Controller/StatusControllerTest.php b/apps/encryption/tests/Controller/StatusControllerTest.php index 1bbcad77411..0c1f209078a 100644 --- a/apps/encryption/tests/Controller/StatusControllerTest.php +++ b/apps/encryption/tests/Controller/StatusControllerTest.php @@ -56,7 +56,7 @@ class StatusControllerTest extends TestCase { */ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetStatus')] public function testGetStatus($status, $expectedStatus): void { - $this->sessionMock->expects($this->once()) + $this->sessionMock->expects($this->atLeastOnce()) ->method('getStatus')->willReturn($status); $result = $this->controller->getStatus(); $data = $result->getData(); diff --git a/apps/encryption/tests/Settings/AdminTest.php b/apps/encryption/tests/Settings/AdminTest.php index 8355cdf6729..10d2a61c527 100644 --- a/apps/encryption/tests/Settings/AdminTest.php +++ b/apps/encryption/tests/Settings/AdminTest.php @@ -10,6 +10,8 @@ namespace OCA\Encryption\Tests\Settings; use OCA\Encryption\Settings\Admin; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; +use OCP\IAppConfig; use OCP\IConfig; use OCP\IL10N; use OCP\ISession; @@ -29,16 +31,20 @@ class AdminTest extends TestCase { protected IConfig&MockObject $config; protected IUserManager&MockObject $userManager; protected ISession&MockObject $session; + protected IInitialState&MockObject $initialState; + protected IAppConfig&MockObject $appConfig; protected function setUp(): void { parent::setUp(); - $this->l = $this->getMockBuilder(IL10N::class)->getMock(); - $this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); - $this->userSession = $this->getMockBuilder(IUserSession::class)->getMock(); - $this->config = $this->getMockBuilder(IConfig::class)->getMock(); - $this->userManager = $this->getMockBuilder(IUserManager::class)->getMock(); - $this->session = $this->getMockBuilder(ISession::class)->getMock(); + $this->l = $this->createMock(IL10N::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->userSession = $this->createMock(IUserSession::class); + $this->config = $this->createMock(IConfig::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->session = $this->createMock(ISession::class); + $this->initialState = $this->createMock(IInitialState::class); + $this->appConfig = $this->createMock(IAppConfig::class); $this->admin = new Admin( $this->l, @@ -46,11 +52,18 @@ class AdminTest extends TestCase { $this->userSession, $this->config, $this->userManager, - $this->session + $this->session, + $this->initialState, + $this->appConfig, ); } public function testGetForm(): void { + $this->appConfig + ->method('getValueBool') + ->willReturnMap([ + ['encryption', 'recoveryAdminEnabled', true] + ]); $this->config ->method('getAppValue') ->willReturnCallback(function ($app, $key, $default) { @@ -62,13 +75,17 @@ class AdminTest extends TestCase { } return $default; }); - $params = [ - 'recoveryEnabled' => '1', - 'initStatus' => '0', - 'encryptHomeStorage' => true, - 'masterKeyEnabled' => true - ]; - $expected = new TemplateResponse('encryption', 'settings-admin', $params, ''); + + $this->initialState + ->expects(self::once()) + ->method('provideInitialState') + ->with('adminSettings', [ + 'recoveryEnabled' => true, + 'initStatus' => '0', + 'encryptHomeStorage' => true, + 'masterKeyEnabled' => true + ]); + $expected = new TemplateResponse('encryption', 'settings', renderAs: ''); $this->assertEquals($expected, $this->admin->getForm()); } diff --git a/build/frontend/apps/encryption b/build/frontend/apps/encryption new file mode 120000 index 00000000000..bb16262bee6 --- /dev/null +++ b/build/frontend/apps/encryption @@ -0,0 +1 @@ +../../../apps/encryption \ No newline at end of file diff --git a/build/frontend/vite.config.ts b/build/frontend/vite.config.ts index 51c10d4baa0..4b1cfbdb113 100644 --- a/build/frontend/vite.config.ts +++ b/build/frontend/vite.config.ts @@ -12,6 +12,11 @@ const modules = { 'settings-admin-example-content': resolve(import.meta.dirname, 'apps/dav/src', 'settings-admin-example-content.ts'), 'settings-personal-availability': resolve(import.meta.dirname, 'apps/dav/src', 'settings-personal-availability.ts'), }, + encryption: { + encryption: resolve(import.meta.dirname, 'apps/encryption/src', 'encryption.ts'), + settings_admin: resolve(import.meta.dirname, 'apps/encryption/src', 'settings-admin.ts'), + settings_personal: resolve(import.meta.dirname, 'apps/encryption/src', 'settings-personal.ts'), + }, federation: { 'settings-admin': resolve(import.meta.dirname, 'apps/federation/src', 'settings-admin.ts'), }, diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 8c34578e3b1..155ccd6ba42 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -1135,9 +1135,6 @@ - - - @@ -1145,11 +1142,6 @@ - - - - -