feat(systemtags): toggle for system tag creation in admin settings

Signed-off-by: nfebe <fenn25.fn@gmail.com>
pull/49514/head
nfebe 2025-01-06 20:06:21 +07:00
parent b4e3eff078
commit f7c46b6809
5 changed files with 110 additions and 4 deletions

@ -1,4 +1,5 @@
<?php <?php
/** /**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
@ -53,6 +54,9 @@ class Server implements IDelegatedSettings {
$this->initialStateService->provideInitialState('profileEnabledGlobally', $this->profileManager->isProfileEnabled()); $this->initialStateService->provideInitialState('profileEnabledGlobally', $this->profileManager->isProfileEnabled());
$this->initialStateService->provideInitialState('profileEnabledByDefault', $this->isProfileEnabledByDefault($this->config)); $this->initialStateService->provideInitialState('profileEnabledByDefault', $this->isProfileEnabledByDefault($this->config));
// Basic settings
$this->initialStateService->provideInitialState('restrictSystemTagsCreationToAdmin', $this->appConfig->getValueString('systemtags', 'restrict_creation_to_admin', 'true'));
return new TemplateResponse('settings', 'settings/admin/server', [ return new TemplateResponse('settings', 'settings/admin/server', [
'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), 'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(),
], ''); ], '');

@ -9,9 +9,9 @@
aria-labelledby="system-tag-form-heading" aria-labelledby="system-tag-form-heading"
@submit.prevent="handleSubmit" @submit.prevent="handleSubmit"
@reset="reset"> @reset="reset">
<h3 id="system-tag-form-heading"> <h4 id="system-tag-form-heading">
{{ t('systemtags', 'Create or edit tags') }} {{ t('systemtags', 'Create or edit tags') }}
</h3> </h4>
<div class="system-tag-form__group"> <div class="system-tag-form__group">
<label for="system-tags-input">{{ t('systemtags', 'Search for a tag to edit') }}</label> <label for="system-tags-input">{{ t('systemtags', 'Search for a tag to edit') }}</label>

@ -0,0 +1,77 @@
<!--
- SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<div id="system-tags-creation-control">
<h4 class="inlineblock">
{{ t('settings', 'System tag creation') }}
</h4>
<p class="settings-hint">
{{ t('settings', 'If enabled, regular accounts will be restricted from creating new tags but will still be able to assign and remove them from their files.') }}
</p>
<NcCheckboxRadioSwitch type="switch"
:checked.sync="systemTagsCreationRestrictedToAdmin"
@update:checked="updateSystemTagsDefault">
{{ t('settings', 'Restrict tag creation to admins only') }}
</NcCheckboxRadioSwitch>
</div>
</template>
<script lang="ts">
import { loadState } from '@nextcloud/initial-state'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { t } from '@nextcloud/l10n'
import logger from '../logger.ts'
import { updateSystemTagsAdminRestriction } from '../services/api.js'
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
export default {
name: 'SystemTagsCreationControl',
components: {
NcCheckboxRadioSwitch,
},
data() {
return {
systemTagsCreationRestrictedToAdmin: loadState('settings', 'restrictSystemTagsCreationToAdmin', '1') === '1',
}
},
methods: {
t,
async updateSystemTagsDefault(isRestricted: boolean) {
try {
const responseData = await updateSystemTagsAdminRestriction(isRestricted)
console.debug('updateSystemTagsDefault', responseData)
this.handleResponse({
isRestricted,
status: responseData.ocs?.meta?.status,
})
} catch (e) {
this.handleResponse({
errorMessage: t('settings', 'Unable to update setting'),
error: e,
})
}
},
handleResponse({ isRestricted, status, errorMessage, error }) {
if (status === 'ok') {
this.systemTagsCreationRestrictedToAdmin = isRestricted
showSuccess(t('settings', `System tag creation is now ${isRestricted ? 'restricted to administrators' : 'allowed for everybody'}`))
return
}
if (errorMessage) {
showError(errorMessage)
logger.error(errorMessage, error)
}
},
},
}
</script>

@ -7,13 +7,14 @@ import type { FileStat, ResponseDataDetailed, WebDAVClientError } from 'webdav'
import type { ServerTag, Tag, TagWithId } from '../types.js' import type { ServerTag, Tag, TagWithId } from '../types.js'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router' import { generateUrl, generateOcsUrl } from '@nextcloud/router'
import { t } from '@nextcloud/l10n' import { t } from '@nextcloud/l10n'
import { davClient } from './davClient.js' import { davClient } from './davClient.js'
import { formatTag, parseIdFromLocation, parseTags } from '../utils' import { formatTag, parseIdFromLocation, parseTags } from '../utils'
import logger from '../logger.ts' import logger from '../logger.ts'
import { emit } from '@nextcloud/event-bus' import { emit } from '@nextcloud/event-bus'
import { confirmPassword } from '@nextcloud/password-confirmation'
export const fetchTagsPayload = `<?xml version="1.0"?> export const fetchTagsPayload = `<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns"> <d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">
@ -203,3 +204,25 @@ export const setTagObjects = async function(tag: TagWithId, type: string, object
}, },
}) })
} }
type OcsResponse = {
ocs: NonNullable<unknown>,
}
export const updateSystemTagsAdminRestriction = async (isAllowed: boolean): Promise<OcsResponse> => {
// Convert to string for compatibility
const isAllowedString = isAllowed ? '1' : '0'
const url = generateOcsUrl('/apps/provisioning_api/api/v1/config/apps/{appId}/{key}', {
appId: 'systemtags',
key: 'restrict_creation_to_admin',
})
await confirmPassword()
const res = await axios.post(url, {
value: isAllowedString,
})
return res.data
}

@ -6,10 +6,10 @@
<template> <template>
<NcSettingsSection :name="t('systemtags', 'Collaborative tags')" <NcSettingsSection :name="t('systemtags', 'Collaborative tags')"
:description="t('systemtags', 'Collaborative tags are available for all users. Restricted tags are visible to users but cannot be assigned by them. Invisible tags are for internal use, since users cannot see or assign them.')"> :description="t('systemtags', 'Collaborative tags are available for all users. Restricted tags are visible to users but cannot be assigned by them. Invisible tags are for internal use, since users cannot see or assign them.')">
<SystemTagsCreationControl />
<NcLoadingIcon v-if="loadingTags" <NcLoadingIcon v-if="loadingTags"
:name="t('systemtags', 'Loading collaborative tags …')" :name="t('systemtags', 'Loading collaborative tags …')"
:size="32" /> :size="32" />
<SystemTagForm v-else <SystemTagForm v-else
:tags="tags" :tags="tags"
@tag:created="handleCreate" @tag:created="handleCreate"
@ -29,6 +29,7 @@ import { translate as t } from '@nextcloud/l10n'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import SystemTagForm from '../components/SystemTagForm.vue' import SystemTagForm from '../components/SystemTagForm.vue'
import SystemTagsCreationControl from '../components/SystemTagsCreationControl.vue'
import { fetchTags } from '../services/api.js' import { fetchTags } from '../services/api.js'
@ -41,6 +42,7 @@ export default Vue.extend({
NcLoadingIcon, NcLoadingIcon,
NcSettingsSection, NcSettingsSection,
SystemTagForm, SystemTagForm,
SystemTagsCreationControl,
}, },
data() { data() {