Skip to content

Commit

Permalink
Add settings section for admin to set default
Browse files Browse the repository at this point in the history
Signed-off-by: Christopher Ng <chrng8@gmail.com>
  • Loading branch information
Pytal committed Dec 17, 2021
1 parent d617c74 commit a0d0460
Show file tree
Hide file tree
Showing 9 changed files with 327 additions and 3 deletions.
49 changes: 48 additions & 1 deletion apps/provisioning_api/lib/Controller/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -712,12 +712,59 @@ public function editUserMultiValue(
return new DataResponse();
}

// TODO think about alternative way to edit all users

/**
* @PasswordConfirmationRequired
*
* edit all users
*
* @param string $key
* @param string $value
* @return DataResponse
* @throws OCSException
*/
public function editAllUsers(string $key, string $value): DataResponse {
$currentLoggedInUser = $this->userSession->getUser();

$handleUserCallback = function (IUser $user) use ($key, $value) {
$permittedFields = [
IAccountManager::PROPERTY_PROFILE_ENABLED,
];
// Check if permitted to edit this field
if (!in_array($key, $permittedFields)) {
throw new OCSException('', 103);
}

switch ($key) {
case IAccountManager::PROPERTY_PROFILE_ENABLED:
$userAccount = $this->accountManager->getAccount($user);
try {
$userProperty = $userAccount->getProperty($key);
if ($userProperty->getValue() !== $value) {
$userProperty->setValue($value);
}
} catch (PropertyDoesNotExistException $e) {
$userAccount->setProperty($key, $value, IAccountManager::SCOPE_LOCAL, IAccountManager::NOT_VERIFIED);
}
$this->accountManager->updateAccount($userAccount);
break;
}

return true;
};

$this->userManager->callForAllUsers($handleUserCallback);

return new DataResponse();
}

/**
* @NoAdminRequired
* @NoSubAdminRequired
* @PasswordConfirmationRequired
*
* edit users
* edit a user
*
* @param string $userId
* @param string $key
Expand Down
21 changes: 21 additions & 0 deletions apps/settings/lib/Settings/Admin/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
*/
namespace OCA\Settings\Settings\Admin;

use OC\Profile\ProfileManager;
use OCP\Accounts\IAccountManager;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\IDBConnection;
Expand All @@ -36,6 +39,12 @@ class Server implements IDelegatedSettings {

/** @var IDBConnection */
private $connection;
/** @var IAccountManager */
private $accountManager;
/** @var IInitialState */
private $initialStateService;
/** @var ProfileManager */
private $profileManager;
/** @var ITimeFactory */
private $timeFactory;
/** @var IConfig */
Expand All @@ -44,10 +53,16 @@ class Server implements IDelegatedSettings {
private $l;

public function __construct(IDBConnection $connection,
IAccountManager $accountManager,
IInitialState $initialStateService,
ProfileManager $profileManager,
ITimeFactory $timeFactory,
IConfig $config,
IL10N $l) {
$this->connection = $connection;
$this->accountManager = $accountManager;
$this->initialStateService = $initialStateService;
$this->profileManager = $profileManager;
$this->timeFactory = $timeFactory;
$this->config = $config;
$this->l = $l;
Expand All @@ -65,8 +80,14 @@ public function getForm() {
'cronErrors' => $this->config->getAppValue('core', 'cronErrors'),
'cli_based_cron_possible' => function_exists('posix_getpwuid'),
'cli_based_cron_user' => function_exists('posix_getpwuid') ? posix_getpwuid(fileowner(\OC::$configDir . 'config.php'))['name'] : '',
'globalProfileEnabled' => $this->profileManager->isProfileEnabled(),
];

$this->initialStateService->provideInitialState('globalProfileEnabled', $this->profileManager->isProfileEnabled());
$this->initialStateService->provideInitialState('profileSettings', [
'profileDefaultEnabled' => $this->accountManager->isProfileDefaultEnabled(),
]);

return new TemplateResponse('settings', 'settings/admin/server', $parameters, '');
}

Expand Down
148 changes: 148 additions & 0 deletions apps/settings/src/components/BasicSettings/ProfileSettings.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<!--
- @copyright 2021 Christopher Ng <chrng8@gmail.com>
-
- @author Christopher Ng <chrng8@gmail.com>
-
- @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 <http://www.gnu.org/licenses/>.
-
-->

<template>
<div
id="profile-settings"
class="section"
:class="{ disabled }">
<h2 class="inlineblock">
{{ t('settings', 'Profile') }}
</h2>

<p class="settings-hint">
{{ t('settings', 'Configure whether profile is enabled by default for new users. Users may enable or disable their own profiles individually.') }}
</p>

<div class="profile-settings__option-group">
<CheckboxRadioSwitch
type="switch"
:checked.sync="forceChangeExistingUsers"
@update:checked="onDefaultEnableProfileChange">
{{ t('settings', 'Apply to existing users as well (by default only applies to newly created users)') }}
</CheckboxRadioSwitch>
</div>

<div class="profile-settings__option-group">
<div class="profile-settings__option-group__option">
<input
id="default-enabled"
name="profile-default"
class="radio"
type="radio"
:checked="initialProfileDefaultEnabled"
@change="onDefaultEnableProfileChange">
<label for="default-enabled">
{{ t('settings', 'Enabled by default') }}
</label>
</div>

<div class="profile-settings__option-group__option">
<input
id="default-disabled"
name="profile-default"
class="radio"
type="radio"
:checked="!initialProfileDefaultEnabled"
@change="onDefaultEnableProfileChange">
<label for="default-disabled">
{{ t('settings', 'Disabled by default') }}
</label>
</div>
</div>
</div>
</template>

<script>
import { emit } from '@nextcloud/event-bus'
import { loadState } from '@nextcloud/initial-state'
import { showError } from '@nextcloud/dialogs'

import CheckboxRadioSwitch from '@nextcloud/vue/dist/Components/CheckboxRadioSwitch'

import { saveDefaultEnableProfile } from '../../service/ProfileService'
import { validateBoolean } from '../../utils/validate'

const { profileDefaultEnabled } = loadState('settings', 'profileSettings', {})

export default {
name: 'ProfileSettings',

components: {
CheckboxRadioSwitch,
},

data() {
return {
forceChangeExistingUsers: false,
initialProfileDefaultEnabled: profileDefaultEnabled,
}
},

methods: {
async onDefaultEnableProfileChange(e) {
const isEnabled = e.target.id === 'default-enabled' && e.target.checked
this.$emit('update:profile-default-enabled', isEnabled)

if (validateBoolean(isEnabled)) {
await this.updateDefaultEnableProfile(isEnabled, this.forceChangeExistingUsers)
}
},

async updateDefaultEnableProfile(isEnabled, forceChangeExistingUsers) {
try {
const responseData = await saveDefaultEnableProfile(isEnabled, forceChangeExistingUsers)
this.handleResponse({
isEnabled,
status: responseData.ocs?.meta?.status,
})
} catch (e) {
this.handleResponse({
errorMessage: t('settings', 'Unable to update default profile enabled state'),
error: e,
})
}
},

handleResponse({ isEnabled, status, errorMessage, error }) {
if (status === 'ok') {
// Ensure that local state reflects server state
this.initialDProfileDefaultEnabled = isEnabled
emit('settings:profile-default-enabled:updated', isEnabled)
} else {
showError(errorMessage)
this.logger.error(errorMessage, error)
}
},
},
}
</script>

<style lang="scss" scoped>
.profile-settings {
&__option-group {
&__option {
margin-bottom: 8px;
}
}
}
</style>
49 changes: 49 additions & 0 deletions apps/settings/src/main-admin-basic-settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* @copyright 2021 Christopher Ng <chrng8@gmail.com>
*
* @author Christopher Ng <chrng8@gmail.com>
*
* @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 <http://www.gnu.org/licenses/>.
*
*/

import Vue from 'vue'
import { getRequestToken } from '@nextcloud/auth'
import { loadState } from '@nextcloud/initial-state'
import { translate as t } from '@nextcloud/l10n'
import '@nextcloud/dialogs/styles/toast.scss'

import logger from './logger'

import ProfileSettings from './components/BasicSettings/ProfileSettings'

const globalProfileEnabled = loadState('settings', 'globalProfileEnabled', true)

__webpack_nonce__ = btoa(getRequestToken())

Vue.mixin({
props: {
logger,
},
methods: {
t,
},
})

if (globalProfileEnabled) {
const ProfileSettingsView = Vue.extend(ProfileSettings)
new ProfileSettingsView().$mount('.vue-admin-profile-settings')
}
37 changes: 37 additions & 0 deletions apps/settings/src/service/ProfileService.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,40 @@ export const saveProfileParameterVisibility = async(paramId, visibility) => {

return res.data
}

/**
* Save the default profile enabled state
*
* @param {string} isEnabled the default state
* @param {string} forceChangeExistingUsers whether to force change this setting for existing users
* @returns {object}
*/
export const saveDefaultEnableProfile = async(isEnabled, forceChangeExistingUsers) => {
// TODO allow boolean values on backend route handler
// Convert boolean to string for compatibility
if (typeof isEnabled === 'boolean') {
isEnabled = isEnabled ? '1' : '0'
}

const url = forceChangeExistingUsers
// TODO test v2
// TODO create route handler to force change existing users
? generateOcsUrl(
'/apps/provisioning_api/api/v2/config/apps/{appId}/{key}', {
appId: 'settings',
key: 'profile_default_enabled',
})
: generateOcsUrl(
'/apps/provisioning_api/api/v2/config/apps/{appId}/{key}', {
appId: 'settings',
key: 'profile_default_enabled',
})

await confirmPassword()

const res = await axios.post(url, {
value: isEnabled,
})

return res.data
}
7 changes: 6 additions & 1 deletion apps/settings/templates/settings/admin/server.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
/** @var \OCP\IL10N $l */
/** @var array $_ */

script('settings', [
'vue-settings-admin-basic-settings',
]);
?>

<div class="section" id="backgroundjobs">
Expand Down Expand Up @@ -113,4 +116,6 @@
</form>
</div>

<div class="vue-global-profile-settings"></div>
<?php if ($_['globalProfileEnabled']) : ?>
<div class="vue-admin-profile-settings"></div>
<?php endif; ?>
1 change: 1 addition & 0 deletions apps/settings/webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ module.exports = {
'settings-personal-webauthn': path.join(__dirname, 'src', 'main-personal-webauth'),
'settings-nextcloud-pdf': path.join(__dirname, 'src', 'main-nextcloud-pdf'),
'settings-personal-info': path.join(__dirname, 'src', 'main-personal-info'),
'settings-admin-basic-settings': path.join(__dirname, 'src', 'main-admin-basic-settings'),
},
output: {
path: path.resolve(__dirname, './js'),
Expand Down
Loading

0 comments on commit a0d0460

Please sign in to comment.