Skip to content

Commit ce481be

Browse files
committed
feat: Implement UI for managing Team Folders SSE in Nextcloud security settings
Signed-off-by: Faisal Alghamdi <falghamdi125@gmail.com>
1 parent 53b8d26 commit ce481be

7 files changed

Lines changed: 196 additions & 0 deletions

File tree

appinfo/info.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Folder.
7171

7272
<settings>
7373
<admin>OCA\GroupFolders\Settings\Admin</admin>
74+
<admin>OCA\GroupFolders\Settings\AdminSecurity</admin>
7475
<admin-section>OCA\GroupFolders\Settings\Section</admin-section>
7576
</settings>
7677

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\GroupFolders\Controller;
11+
12+
use OCA\GroupFolders\AppInfo\Application;
13+
use OCP\AppFramework\Http;
14+
use OCP\AppFramework\Http\Attribute\FrontpageRoute;
15+
use OCP\AppFramework\Http\DataResponse;
16+
use OCP\AppFramework\OCSController;
17+
use OCP\IAppConfig;
18+
use OCP\IRequest;
19+
20+
class SettingsController extends OCSController {
21+
public function __construct(
22+
string $appName,
23+
IRequest $request,
24+
private readonly IAppConfig $appConfig,
25+
) {
26+
parent::__construct($appName, $request);
27+
}
28+
29+
/**
30+
* @return DataResponse<Http::STATUS_OK, array{enable_encryption: bool}, array{}>
31+
*/
32+
#[FrontpageRoute(verb: 'GET', url: '/settings')]
33+
public function getSettings(): DataResponse {
34+
return new DataResponse([
35+
'enable_encryption' => $this->appConfig->getValueBool(Application::APP_ID, 'enable_encryption', false),
36+
]);
37+
}
38+
39+
/**
40+
* @return DataResponse<Http::STATUS_OK, array{}, array{}>
41+
*/
42+
#[FrontpageRoute(verb: 'POST', url: '/settings')]
43+
public function setSettings(bool $enable): DataResponse {
44+
$this->appConfig->setValueMixed(Application::APP_ID, 'enable_encryption', $enable ? 'true' : 'false');
45+
return new DataResponse([]);
46+
}
47+
}

lib/Settings/AdminSecurity.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\GroupFolders\Settings;
11+
12+
use OCA\GroupFolders\AppInfo\Application;
13+
use OCP\AppFramework\Http\TemplateResponse;
14+
use OCP\AppFramework\Services\IInitialState;
15+
use OCP\IAppConfig;
16+
use OCP\Settings\ISettings;
17+
use OCP\Util;
18+
19+
class AdminSecurity implements ISettings {
20+
public function __construct(
21+
private readonly IInitialState $initialState,
22+
private readonly IAppConfig $appConfig,
23+
) {
24+
}
25+
26+
#[\Override]
27+
public function getForm(): TemplateResponse {
28+
$this->initialState->provideInitialState(
29+
'server_side_encryption',
30+
$this->appConfig->getValueString('encryption', 'enabled', 'no'),
31+
);
32+
$this->initialState->provideInitialState(
33+
'enable_encryption',
34+
$this->appConfig->getValueBool(Application::APP_ID, 'enable_encryption', false),
35+
);
36+
37+
Util::addStyle('encryption', 'settings_admin');
38+
Util::addStyle(Application::APP_ID, Application::APP_ID . '-settings-security');
39+
Util::addScript(Application::APP_ID, Application::APP_ID . '-settings-security');
40+
41+
return new TemplateResponse(Application::APP_ID, 'settings-security', []);
42+
}
43+
44+
#[\Override]
45+
public function getSection(): string {
46+
return 'security';
47+
}
48+
49+
#[\Override]
50+
public function getPriority(): int {
51+
return 90;
52+
}
53+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<!--
2+
- SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
- SPDX-License-Identifier: AGPL-3.0-or-later
4+
-->
5+
6+
<script setup lang="ts">
7+
import { ref } from 'vue'
8+
import { NcNoteCard, NcCheckboxRadioSwitch, NcSettingsSection } from '@nextcloud/vue'
9+
import { loadState } from '@nextcloud/initial-state'
10+
import axios from '@nextcloud/axios'
11+
import { generateUrl } from '@nextcloud/router'
12+
import { showError } from '@nextcloud/dialogs'
13+
import { t } from '@nextcloud/l10n'
14+
15+
const serverSideEncryptionEnabled = ref<string>(loadState<string>('groupfolders', 'server_side_encryption', 'no'))
16+
const folderEncryptionEnabled = ref<boolean>(loadState<boolean>('groupfolders', 'enable_encryption', false))
17+
18+
const loading = ref(false)
19+
20+
async function handleChange(isEnabled: boolean) {
21+
if (loading.value || serverSideEncryptionEnabled.value === 'no' || (folderEncryptionEnabled.value == true && isEnabled == false)) {
22+
return
23+
}
24+
const previous = folderEncryptionEnabled.value
25+
folderEncryptionEnabled.value = isEnabled
26+
loading.value = true
27+
try {
28+
await axios.post(generateUrl('apps/groupfolders/settings'), { enable: isEnabled })
29+
} catch {
30+
folderEncryptionEnabled.value = previous
31+
showError(t('groupfolders', 'Failed to update encryption setting'))
32+
} finally {
33+
loading.value = false
34+
}
35+
}
36+
</script>
37+
38+
<template>
39+
<NcSettingsSection :name="t('groupfolders', 'Team folders encryption')">
40+
<NcCheckboxRadioSwitch
41+
:class="{ disabled: folderEncryptionEnabled || serverSideEncryptionEnabled === 'no' }"
42+
type="switch"
43+
:model-value="folderEncryptionEnabled"
44+
:aria-disabled="loading || serverSideEncryptionEnabled === 'no' || folderEncryptionEnabled == true"
45+
:loading="loading"
46+
:description="!folderEncryptionEnabled ? t('groupfolders', 'Encrypt team folders using server-side encryption. Remember that the data cannot be accessed if the encryption key is lost.') : null"
47+
@update:model-value="handleChange">
48+
{{ t('groupfolders', 'Enable Team Folders encryption') }}
49+
</NcCheckboxRadioSwitch>
50+
51+
<p v-if=" serverSideEncryptionEnabled === 'yes' && folderEncryptionEnabled == true" id="team-folders-encryption-disable-hint" class="disable-hint">
52+
{{ t('groupfolders', 'Disabling team folders encryption is only possible using OCC, please refer to the documentation.') }}
53+
</p>
54+
55+
<NcNoteCard v-if="serverSideEncryptionEnabled === 'no'" type="warning"
56+
:text="t('settings', 'Team Folders cannot be encrypted on the server because server-side encryption is disabled.')" />
57+
</NcSettingsSection>
58+
</template>
59+
60+
<style scoped>
61+
62+
.disabled {
63+
opacity: .75;
64+
}
65+
66+
.disabled :deep(*) {
67+
cursor: not-allowed !important;
68+
}
69+
70+
.disable-hint {
71+
color: var(--color-text-maxcontrast);
72+
padding-inline-start: 10px;
73+
}
74+
</style>

src/settings-security/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*!
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { createApp } from 'vue'
7+
import TeamFoldersEncryption from '../components/TeamFoldersEncryption.vue'
8+
9+
const app = createApp(TeamFoldersEncryption)
10+
app.mount('#groupfolders-settings-section')

templates/settings-security.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
?>
10+
<div id="groupfolders-settings-section"></div>

vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { join } from 'node:path'
1010
export default createAppConfig({
1111
initFiles: join(__dirname, 'src/init-files.ts'),
1212
settings: join(__dirname, 'src/settings/index.tsx'),
13+
'settings-security': join(__dirname, 'src/settings-security/index.ts'),
1314
}, {
1415
createEmptyCSSEntryPoints: true,
1516
emptyOutputDirectory: {

0 commit comments

Comments
 (0)