Merge pull request #9488 from nextcloud/disabled-users-fix

Added disabled count per groups & fixed disabled users query
This commit is contained in:
blizzz 2018-05-25 15:54:47 +02:00 committed by GitHub
commit 760b28ba4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 370 additions and 105 deletions

View File

@ -90,12 +90,12 @@ abstract class AUserData extends OCSController {
}
// Should be at least Admin Or SubAdmin!
if( $this->groupManager->isAdmin($currentLoggedInUser->getUID())
if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())
|| $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
$data['enabled'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'enabled', 'true') === 'true';
} else {
// Check they are looking up themselves
if($currentLoggedInUser->getUID() !== $targetUserObject->getUID()) {
if ($currentLoggedInUser->getUID() !== $targetUserObject->getUID()) {
return $data;
}
}

View File

@ -111,7 +111,12 @@ class GroupsController extends AUserData {
$groups = $this->groupManager->search($search, $limit, $offset);
$groups = array_map(function($group) {
/** @var IGroup $group */
return ['id' => $group->getGID(), 'displayname' => $group->getDisplayName()];
return [
'id' => $group->getGID(),
'displayname' => $group->getDisplayName(),
'usercount' => $group->count(),
'disabled' => $group->countDisabled()
];
}, $groups);
return new DataResponse(['groups' => $groups]);
@ -202,6 +207,10 @@ class GroupsController extends AUserData {
// Do not insert empty entry
if(!empty($userData)) {
$usersDetails[$userId] = $userData;
} else {
// Logged user does not have permissions to see this user
// only showing its id
$usersDetails[$userId] = ['id' => $userId];
}
}
return new DataResponse(['users' => $usersDetails]);

View File

@ -180,6 +180,10 @@ class UsersController extends AUserData {
// Do not insert empty entry
if (!empty($userData)) {
$usersDetails[$userId] = $userData;
} else {
// Logged user does not have permissions to see this user
// only showing its id
$usersDetails[$userId] = ['id' => $userId];
}
}

View File

@ -101,6 +101,12 @@ class GroupsControllerTest extends \Test\TestCase {
$group
->method('getDisplayName')
->willReturn($gid.'-name');
$group
->method('count')
->willReturn(123);
$group
->method('countDisabled')
->willReturn(11);
return $group;
}
@ -205,8 +211,18 @@ class GroupsControllerTest extends \Test\TestCase {
$result = $this->api->getGroupsDetails($search, $limit, $offset);
$this->assertEquals(['groups' => [
Array('id' => 'group1', 'displayname' => 'group1-name'),
Array('id' => 'group2', 'displayname' => 'group2-name')
Array(
'id' => 'group1',
'displayname' => 'group1-name',
'usercount' => 123,
'disabled' => 11
),
Array(
'id' => 'group2',
'displayname' => 'group2-name',
'usercount' => 123,
'disabled' => 11
)
]], $result->getData());
}

View File

@ -188,6 +188,7 @@ return array(
'OCP\\GroupInterface' => $baseDir . '/lib/public/GroupInterface.php',
'OCP\\Group\\Backend\\ABackend' => $baseDir . '/lib/public/Group/Backend/ABackend.php',
'OCP\\Group\\Backend\\IAddToGroupBackend' => $baseDir . '/lib/public/Group/Backend/IAddToGroupBackend.php',
'OCP\\Group\\Backend\\ICountDisabledInGroup' => $baseDir . '/lib/public/Group/Backend/ICountDisabledInGroup.php',
'OCP\\Group\\Backend\\ICountUsersBackend' => $baseDir . '/lib/public/Group/Backend/ICountUsersBackend.php',
'OCP\\Group\\Backend\\ICreateGroupBackend' => $baseDir . '/lib/public/Group/Backend/ICreateGroupBackend.php',
'OCP\\Group\\Backend\\IDeleteGroupBackend' => $baseDir . '/lib/public/Group/Backend/IDeleteGroupBackend.php',

View File

@ -218,6 +218,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\GroupInterface' => __DIR__ . '/../../..' . '/lib/public/GroupInterface.php',
'OCP\\Group\\Backend\\ABackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ABackend.php',
'OCP\\Group\\Backend\\IAddToGroupBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IAddToGroupBackend.php',
'OCP\\Group\\Backend\\ICountDisabledInGroup' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ICountDisabledInGroup.php',
'OCP\\Group\\Backend\\ICountUsersBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ICountUsersBackend.php',
'OCP\\Group\\Backend\\ICreateGroupBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ICreateGroupBackend.php',
'OCP\\Group\\Backend\\IDeleteGroupBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IDeleteGroupBackend.php',

View File

@ -5,6 +5,7 @@
* @author Aaron Wood <aaronjwood@gmail.com>
* @author Loki3000 <github@labcms.ru>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0
*
@ -40,8 +41,10 @@
namespace OC\Group;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Group\Backend\ABackend;
use OCP\Group\Backend\IAddToGroupBackend;
use OCP\Group\Backend\ICountDisabledInGroup;
use OCP\Group\Backend\ICountUsersBackend;
use OCP\Group\Backend\ICreateGroupBackend;
use OCP\Group\Backend\IDeleteGroupBackend;
@ -53,6 +56,7 @@ use OCP\IDBConnection;
*/
class Database extends ABackend
implements IAddToGroupBackend,
ICountDisabledInGroup,
ICountUsersBackend,
ICreateGroupBackend,
IDeleteGroupBackend,
@ -373,4 +377,35 @@ class Database extends ABackend
return $count;
}
/**
* get the number of disabled users in a group
*
* @param string $search
* @return int|bool
*/
public function countDisabledInGroup(string $gid): int {
$this->fixDI();
$query = $this->dbConn->getQueryBuilder();
$query->select($query->createFunction('COUNT(Distinct uid)'))
->from('preferences', 'p')
->innerJoin('p', 'group_user', 'g', 'p.userid = g.uid')
->where($query->expr()->eq('appid', $query->createNamedParameter('core')))
->andWhere($query->expr()->eq('configkey', $query->createNamedParameter('enabled')))
->andWhere($query->expr()->eq('configvalue', $query->createNamedParameter('false'), IQueryBuilder::PARAM_STR))
->andWhere($query->expr()->eq('gid', $query->createNamedParameter($gid), IQueryBuilder::PARAM_STR));
$result = $query->execute();
$count = $result->fetchColumn();
$result->closeCursor();
if ($count !== false) {
$count = (int)$count;
} else {
$count = 0;
}
return $count;
}
}

View File

@ -10,6 +10,7 @@
* @author Robin McCorkell <robin@mccorkell.me.uk>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Vincent Petry <pvince81@owncloud.com>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0
*
@ -31,6 +32,7 @@ namespace OC\Group;
use OCP\IGroup;
use OCP\IUser;
use OCP\Group\Backend\ICountDisabledInGroup;
class Group implements IGroup {
/** @var null|string */
@ -236,6 +238,26 @@ class Group implements IGroup {
return $users;
}
/**
* returns the number of disabled users
*
* @return int|bool
*/
public function countDisabled() {
$users = false;
foreach ($this->backends as $backend) {
if($backend instanceOf ICountDisabledInGroup) {
if($users === false) {
//we could directly add to a bool variable, but this would
//be ugly
$users = 0;
}
$users += $backend->countDisabledInGroup($this->gid);
}
}
return $users;
}
/**
* search for users in the group by displayname
*

View File

@ -8,6 +8,7 @@
* @author Morris Jobke <hey@morrisjobke.de>
* @author Stephan Peijnik <speijnik@anexia-it.com>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0
*
@ -28,6 +29,7 @@
namespace OC\Group;
use OCP\IUserSession;
use OCP\IGroupManager;
class MetaData {
const SORT_NONE = 0;
@ -40,7 +42,7 @@ class MetaData {
protected $isAdmin;
/** @var array */
protected $metaData = array();
/** @var \OCP\IGroupManager */
/** @var IGroupManager */
protected $groupManager;
/** @var bool */
protected $sorting = false;
@ -50,13 +52,14 @@ class MetaData {
/**
* @param string $user the uid of the current user
* @param bool $isAdmin whether the current users is an admin
* @param \OCP\IGroupManager $groupManager
* @param IGroupManager $groupManager
* @param IUserManager $userManager
* @param IUserSession $userSession
*/
public function __construct(
$user,
$isAdmin,
\OCP\IGroupManager $groupManager,
IGroupManager $groupManager,
IUserSession $userSession
) {
$this->user = $user;
@ -155,13 +158,14 @@ class MetaData {
* creates an array containing the group meta data
* @param \OCP\IGroup $group
* @param string $userSearch
* @return array with the keys 'id', 'name' and 'usercount'
* @return array with the keys 'id', 'name', 'usercount' and 'disabled'
*/
private function generateGroupMetaData(\OCP\IGroup $group, $userSearch) {
return array(
'id' => $group->getGID(),
'name' => $group->getDisplayName(),
'usercount' => $this->sorting === self::SORT_USERCOUNT ? $group->count($userSearch) : 0,
'disabled' => $group->countDisabled()
);
}
@ -184,7 +188,7 @@ class MetaData {
* @param string $search a search string
* @return \OCP\IGroup[]
*/
protected function getGroups($search = '') {
public function getGroups($search = '') {
if($this->isAdmin) {
return $this->groupManager->search($search);
} else {

View File

@ -34,6 +34,7 @@ namespace OC\User;
use OC\Hooks\PublicEmitter;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IUser;
use OCP\IGroup;
use OCP\IUserBackend;
use OCP\IUserManager;
use OCP\IConfig;
@ -384,6 +385,24 @@ class Manager extends PublicEmitter implements IUserManager {
return $userCountStatistics;
}
/**
* returns how many users per backend exist in the requested groups (if supported by backend)
*
* @param IGroup[] $groups an array of gid to search in
* @return array|int an array of backend class as key and count number as value
* if $hasLoggedIn is true only an int is returned
*/
public function countUsersOfGroups(array $groups) {
$users = [];
foreach($groups as $group) {
$usersIds = array_map(function($user) {
return $user->getUID();
}, $group->getUsers());
$users = array_merge($users, $usersIds);
}
return count(array_unique($users));
}
/**
* The callback is executed for each user on each backend.
* If the callback returns false no further users will be retrieved.
@ -420,12 +439,12 @@ class Manager extends PublicEmitter implements IUserManager {
}
/**
* returns how many users have logged in once
* returns how many users are disabled
*
* @return int
* @since 12.0.0
*/
public function countDisabledUsers() {
public function countDisabledUsers(): int {
$queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
$queryBuilder->select($queryBuilder->createFunction('COUNT(*)'))
->from('preferences')
@ -433,12 +452,48 @@ class Manager extends PublicEmitter implements IUserManager {
->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('enabled')))
->andWhere($queryBuilder->expr()->eq('configvalue', $queryBuilder->createNamedParameter('false'), IQueryBuilder::PARAM_STR));
$query = $queryBuilder->execute();
$result = $queryBuilder->execute();
$count = $result->fetchColumn();
$result->closeCursor();
if ($count !== false) {
$count = (int)$count;
} else {
$count = 0;
}
$result = (int)$query->fetchColumn();
$query->closeCursor();
return $count;
}
return $result;
/**
* returns how many users are disabled in the requested groups
*
* @param array $groups groupids to search
* @return int
* @since 14.0.0
*/
public function countDisabledUsersOfGroups(array $groups): int {
$queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
$queryBuilder->select($queryBuilder->createFunction('COUNT(Distinct uid)'))
->from('preferences', 'p')
->innerJoin('p', 'group_user', 'g', 'p.userid = g.uid')
->where($queryBuilder->expr()->eq('appid', $queryBuilder->createNamedParameter('core')))
->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('enabled')))
->andWhere($queryBuilder->expr()->eq('configvalue', $queryBuilder->createNamedParameter('false'), IQueryBuilder::PARAM_STR))
->andWhere($queryBuilder->expr()->in('gid', $queryBuilder->createNamedParameter($groups, IQueryBuilder::PARAM_STR_ARRAY)));
$result = $queryBuilder->execute();
$count = $result->fetchColumn();
$result->closeCursor();
if ($count !== false) {
$count = (int)$count;
} else {
$count = 0;
}
return $count;
}
/**

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.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/>.
*
*/
namespace OCP\Group\Backend;
/**
* @since 14.0.0
*/
interface ICountDisabledInGroup {
/**
* @since 14.0.0
*/
public function countDisabledInGroup(string $gid): int;
}

View File

@ -100,6 +100,14 @@ interface IGroup {
*/
public function count($search = '');
/**
* returns the number of disabled users
*
* @return int|bool
* @since 14.0.0
*/
public function countDisabled();
/**
* search for users in the group by displayname
*

View File

@ -187,34 +187,35 @@ class UsersController extends Controller {
list($adminGroup, $groups) = $groupsInfo->get();
if ($this->isAdmin) {
$subAdmins = $this->groupManager->getSubAdmin()->getAllSubAdmins();
// New class returns IUser[] so convert back
$result = [];
foreach ($subAdmins as $subAdmin) {
$result[] = [
'gid' => $subAdmin['group']->getGID(),
'uid' => $subAdmin['user']->getUID(),
];
}
$subAdmins = $result;
$disabledUsers = $isLDAPUsed ? 0 : $this->userManager->countDisabledUsers();
$userCount = array_reduce($this->userManager->countUsers(), function($v, $w) {
return $v + (int)$w;
}, 0);
} else {
/* Retrieve group IDs from $groups array, so we can pass that information into OC_Group::displayNamesInGroups() */
$gids = array();
foreach($groups as $group) {
if (isset($group['id'])) {
$gids[] = $group['id'];
// User is subadmin !
// Map group list to names to retrieve the countDisabledUsersOfGroups
$userGroups = $this->groupManager->getUserGroups($user);
$groupsNames = [];
$userCount = 0;
foreach($groups as $key => $group) {
// $userCount += (int)$group['usercount'];
array_push($groupsNames, $group['name']);
// we prevent subadmins from looking up themselves
// so we lower the count of the groups he belongs to
if (array_key_exists($group['id'], $userGroups)) {
$groups[$key]['usercount']--;
$userCount = -1; // we also lower from one the total count
}
}
$subAdmins = false;
};
$userCount += $this->userManager->countUsersOfGroups($groupsInfo->getGroups());
$disabledUsers = $isLDAPUsed ? 0 : $this->userManager->countDisabledUsersOfGroups($groupsNames);
}
$disabledUsers = $isLDAPUsed ? 0 : $this->userManager->countDisabledUsers();
$disabledUsersGroup = [
'id' => 'disabled',
'name' => 'Disabled users',
'usercount' => $disabledUsers
];
$allGroups = array_merge_recursive($adminGroup, $groups);
/* QUOTAS PRESETS */
$quotaPreset = $this->config->getAppValue('files', 'quota_preset', '1 GB, 5 GB, 10 GB');
@ -227,11 +228,6 @@ class UsersController extends Controller {
\OC::$server->getEventDispatcher()->dispatch('OC\Settings\Users::loadAdditionalScripts');
/* TOTAL USERS COUNT */
$userCount = array_reduce($this->userManager->countUsers(), function($v, $w) {
return $v + (int)$w;
}, 0);
/* LANGUAGES */
$languages = $this->l10nFactory->getLanguages();
@ -241,10 +237,9 @@ class UsersController extends Controller {
$serverData['groups'] = array_merge_recursive($adminGroup, [$disabledUsersGroup], $groups);
// Various data
$serverData['isAdmin'] = $this->isAdmin;
$serverData['subadmins'] = $subAdmins;
$serverData['sortGroups'] = $sortGroupsBy;
$serverData['quotaPreset'] = $quotaPreset;
$serverData['userCount'] = $userCount-$disabledUsers;
$serverData['userCount'] = $userCount - $disabledUsers;
$serverData['languages'] = $languages;
$serverData['defaultLanguage'] = $this->config->getSystemValue('default_language', 'en');
// Settings

View File

@ -1320,6 +1320,10 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
.userActions {
width: 100px;
}
.obfuscated {
width: 400px;
opacity: .7;
}
&#grid-header,
&#new-user {
position: sticky;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,7 @@
<button type="button" :id="menu.new.id" :class="menu.new.icon" @click="menu.new.action">{{menu.new.text}}</button>
</div>
<ul :id="menu.id">
<navigation-item v-for="(item, key) in menu.items" :item="item" :key="key" />
<navigation-item v-for="item in menu.items" :item="item" :key="item.key" />
</ul>
<div id="app-settings">
<div id="app-settings-header">

View File

@ -1,21 +1,16 @@
<template>
<li :id="item.id" :class="[{'icon-loading-small': item.loading, 'open': item.opened, 'collapsible': item.collapsible&&item.children&&item.children.length>0 }, item.classes]">
<nav-element :id="item.id" v-bind="navElement(item)"
:class="[{'icon-loading-small': item.loading, 'open': item.opened, 'collapsible': item.collapsible&&item.children&&item.children.length>0 }, item.classes]">
<!-- Bullet -->
<div v-if="item.bullet" class="app-navigation-entry-bullet" :style="{ backgroundColor: item.bullet }"></div>
<!-- Main link -->
<a v-if="item.href" :href="(item.href) ? item.href : '#' " @click="toggleCollapse" :class="item.icon" >
<a :href="(item.href) ? item.href : '#' " @click="toggleCollapse" :class="item.icon">
<img v-if="item.iconUrl" :alt="item.text" :src="item.iconUrl">
{{item.text}}
</a>
<!-- Router link if specified. href OR router -->
<router-link :to="item.router" v-else-if="item.router" :class="item.icon" >
<img v-if="item.iconUrl" :alt="item.text" :src="item.iconUrl">
{{item.text}}
</router-link>
<!-- Popover, counter and button(s) -->
<div v-if="item.utils" class="app-navigation-entry-utils">
<ul>
@ -69,7 +64,7 @@
<ul v-if="item.children">
<navigation-item v-for="(item, key) in item.children" :item="item" :key="key" />
</ul>
</li>
</nav-element>
</template>
<script>
@ -89,7 +84,7 @@ export default {
data() {
return {
openedMenu: false
}
};
},
methods: {
showMenu() {
@ -106,12 +101,29 @@ export default {
cancelEdit() {
// remove the editing class
if (Array.isArray(this.item.classes))
this.item.classes = this.item.classes.filter(item => item !== 'editing');
this.item.classes = this.item.classes.filter(
item => item !== 'editing'
);
},
// This is used to decide which outter element type to use
// li or router-link
navElement(item) {
if (item.href) {
return {
is: 'li'
};
}
return {
is: 'router-link',
tag: 'li',
to: item.router,
exact: true
};
}
},
mounted() {
// prevent click outside event with popupItem.
this.popupItem = this.$el;
},
}
}
};
</script>

View File

@ -171,7 +171,7 @@ export default {
},
filteredUsers() {
if (this.selectedGroup === 'disabled') {
let disabledUsers = this.users.filter(user => user.enabled !== true);
let disabledUsers = this.users.filter(user => user.enabled === false);
if (disabledUsers.length===0 && this.$refs.infiniteLoading && this.$refs.infiniteLoading.isComplete) {
// disabled group is empty, redirection to all users
this.$router.push({name: 'users'});
@ -179,7 +179,11 @@ export default {
}
return disabledUsers;
}
return this.users.filter(user => user.enabled === true);
if (!settings.isAdmin) {
// We don't want subadmins to edit themselves
return this.users.filter(user => user.enabled !== false && user.id !== oc_current_user);
}
return this.users.filter(user => user.enabled !== false);
},
groups() {
// data provided php side + remove the disabled group

View File

@ -1,5 +1,17 @@
<template>
<div class="row" :class="{'disabled': loading.delete || loading.disable}">
<!-- Obfuscated user: Logged in user does not have permissions to see all of the data -->
<div class="row" v-if="Object.keys(user).length ===1">
<div class="avatar" :class="{'icon-loading-small': loading.delete || loading.disable}">
<img alt="" width="32" height="32" :src="generateAvatar(user.id, 32)"
:srcset="generateAvatar(user.id, 64)+' 2x, '+generateAvatar(user.id, 128)+' 4x'"
v-if="!loading.delete && !loading.disable">
</div>
<div class="name">{{user.id}}</div>
<div class="obfuscated">{{t('settings','You do not have permissions to see the details of this user')}}</div>
</div>
<!-- User full data -->
<div class="row" v-else :class="{'disabled': loading.delete || loading.disable}">
<div class="avatar" :class="{'icon-loading-small': loading.delete || loading.disable}">
<img alt="" width="32" height="32" :src="generateAvatar(user.id, 32)"
:srcset="generateAvatar(user.id, 64)+' 2x, '+generateAvatar(user.id, 128)+' 4x'"
@ -314,18 +326,22 @@ export default {
},
/**
* Create a new group
* Create a new group and add user to it
*
* @param {string} groups Group id
* @returns {Promise}
*/
createGroup(gid) {
this.loading = {groups:true, subadmins:true}
this.$store.dispatch('addGroup', gid).then(() => {
this.loading = {groups:false, subadmins:false};
let userid = this.user.id;
this.$store.dispatch('addUserGroup', {userid, gid});
});
this.$store.dispatch('addGroup', gid)
.then(() => {
this.loading = {groups:false, subadmins:false};
let userid = this.user.id;
this.$store.dispatch('addUserGroup', {userid, gid});
})
.catch(() => {
this.loading = {groups:false, subadmins:false};
});
return this.$store.getters.getGroups[this.groups.length];
},
@ -360,6 +376,9 @@ export default {
if (this.$route.params.selectedGroup === gid) {
this.$store.commit('deleteUser', userid);
}
})
.catch(() => {
this.loading.groups = false
});
},

View File

@ -12,6 +12,7 @@ sync(store, router);
Vue.prototype.t = t;
Vue.prototype.OC = OC;
Vue.prototype.oc_userconfig = oc_userconfig;
Vue.prototype.oc_current_user = oc_current_user;
const app = new Vue({
router,

View File

@ -18,6 +18,7 @@ export default new Router({
// if index.php is in the url AND we got this far, then it's working:
// let's keep using index.php in the url
base: OC.generateUrl(''),
linkActiveClass: 'active',
routes: [
{
path: '/:index(index.php/)?settings/users',

View File

@ -10,8 +10,12 @@ const debug = process.env.NODE_ENV !== 'production';
const mutations = {
API_FAILURE(state, error) {
let message = error.error.response.data.ocs.meta.message;
OC.Notification.showHtml(t('settings','An error occured during the request. Unable to proceed.')+'<br>'+message, {timeout: 7});
try {
let message = error.error.response.data.ocs.meta.message;
OC.Notification.showHtml(t('settings','An error occured during the request. Unable to proceed.')+'<br>'+message, {timeout: 7});
} catch(e) {
OC.Notification.showTemporary(t('settings','An error occured during the request. Unable to proceed.'));
}
console.log(state, error);
}
};

View File

@ -6,12 +6,21 @@ const orderGroups = function(groups, orderBy) {
* https://github.com/nextcloud/server/blob/208e38e84e1a07a49699aa90dc5b7272d24489f0/lib/private/Group/MetaData.php#L34
*/
if (orderBy === 1) {
return groups.sort((a, b) => a.usercount < b.usercount);
return groups.sort((a, b) => a.usercount-a.disabled < b.usercount - b.disabled);
} else {
return groups.sort((a, b) => a.name.localeCompare(b.name));
}
};
const defaults = {
group: {
id: '',
name: '',
usercount: 0,
disabled: 0
}
}
const state = {
users: [],
groups: [],
@ -33,18 +42,20 @@ const mutations = {
state.minPasswordLength = length!=='' ? length : 0;
},
initGroups(state, {groups, orderBy, userCount}) {
state.groups = groups;
state.groups = groups.map(group => Object.assign({}, defaults.group, group));
state.orderBy = orderBy;
state.userCount = userCount;
state.groups = orderGroups(state.groups, state.orderBy);
},
addGroup(state, gid) {
try {
state.groups.push({
// extend group to default values
let group = Object.assign({}, defaults.group, {
id: gid,
name: gid,
usercount: 0 // user will be added after the creation
name: gid
});
state.groups.push(group);
state.groups = orderGroups(state.groups, state.orderBy);
} catch (e) {
console.log('Can\'t create group', e);
@ -58,19 +69,23 @@ const mutations = {
},
addUserGroup(state, { userid, gid }) {
let group = state.groups.find(groupSearch => groupSearch.id == gid);
if (group) {
group.usercount++; // increase count
let user = state.users.find(user => user.id == userid);
// increase count if user is enabled
if (group && user.enabled) {
group.usercount++;
}
let groups = state.users.find(user => user.id == userid).groups;
let groups = user.groups;
groups.push(gid);
state.groups = orderGroups(state.groups, state.orderBy);
},
removeUserGroup(state, { userid, gid }) {
let group = state.groups.find(groupSearch => groupSearch.id == gid);
if (group) {
group.usercount--; // lower count
let user = state.users.find(user => user.id == userid);
// lower count if user is enabled
if (group && user.enabled) {
group.usercount--;
}
let groups = state.users.find(user => user.id == userid).groups;
let groups = user.groups;
groups.splice(groups.indexOf(gid),1);
state.groups = orderGroups(state.groups, state.orderBy);
},
@ -90,11 +105,15 @@ const mutations = {
state.users.push(response.data.ocs.data);
},
enableDisableUser(state, { userid, enabled }) {
state.users.find(user => user.id == userid).enabled = enabled;
let user = state.users.find(user => user.id == userid);
user.enabled = enabled;
// increment or not
state.groups.find(group => group.id == 'disabled').usercount += enabled ? -1 : 1;
state.userCount += enabled ? 1 : -1;
console.log(enabled);
user.groups.forEach(group => {
// Increment disabled count
state.groups.find(groupSearch => groupSearch.id == group).disabled += enabled ? -1 : 1;
});
},
setUserData(state, { userid, key, value }) {
if (key === 'quota') {
@ -236,7 +255,12 @@ const actions = {
return api.post(OC.linkToOCS(`cloud/groups`, 2), {groupid: gid})
.then((response) => context.commit('addGroup', gid))
.catch((error) => {throw error;});
}).catch((error) => context.commit('API_FAILURE', { userid, error }));
}).catch((error) => {
context.commit('API_FAILURE', { gid, error });
// let's throw one more time to prevent the view
// from adding the user to a group that doesn't exists
throw error;
});
},
/**
@ -285,7 +309,12 @@ const actions = {
return api.delete(OC.linkToOCS(`cloud/users/${userid}/groups`, 2), { groupid: gid })
.then((response) => context.commit('removeUserGroup', { userid, gid }))
.catch((error) => {throw error;});
}).catch((error) => context.commit('API_FAILURE', { userid, error }));
}).catch((error) => {
context.commit('API_FAILURE', { userid, error });
// let's throw one more time to prevent
// the view from removing the user row on failure
throw error;
});
},
/**

View File

@ -233,13 +233,22 @@ export default {
groups = groups.map(group => {
let item = {};
item.id = group.id.replace(' ', '_');
item.classes = []; // empty classes, active will be set later
item.router = { // router link to
item.key = item.id;
item.utils = {}
// router link to
item.router = {
name: 'group',
params: {selectedGroup: group.id}
};
item.text = group.name; // group name
item.utils = {counter: group.usercount}; // users count
// group name
item.text = group.name;
// users count
if (group.usercount - group.disabled > 0) {
item.utils.counter = group.usercount - group.disabled;
}
if (item.id !== 'admin' && item.id !== 'disabled' && this.settings.isAdmin) {
// add delete button on real groups
@ -268,21 +277,17 @@ export default {
}
// Add everyone group
groups.unshift({
let everyoneGroup = {
id: 'everyone',
classes: [],
key: 'everyone',
router: {name:'users'},
text: t('settings', 'Everyone'),
utils: {counter: this.userCount}
});
// Set current group as active
let activeGroup = groups.findIndex(group => group.id === this.selectedGroup);
if (activeGroup >= 0) {
groups[activeGroup].classes.push('active');
} else {
groups[0].classes.push('active');
};
// users count
if (this.userCount > 0) {
everyoneGroup.utils = {counter: this.userCount};
}
groups.unshift(everyoneGroup);
// Return
return {