mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-11 11:51:27 +00:00
admin add ilter api for users (#6127)
* admin add ilter api for users * change filter users UI * change code format --------- Co-authored-by: 孙永强 <11704063+s-yongqiang@user.noreply.gitee.com> Co-authored-by: Michael An <2331806369@qq.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import OpMenu from '../../../components/dialog/op-menu';
|
|||||||
import SysAdminUserSetQuotaDialog from '../../../components/dialog/sysadmin-dialog/set-quota';
|
import SysAdminUserSetQuotaDialog from '../../../components/dialog/sysadmin-dialog/set-quota';
|
||||||
import CommonOperationConfirmationDialog from '../../../components/dialog/common-operation-confirmation-dialog';
|
import CommonOperationConfirmationDialog from '../../../components/dialog/common-operation-confirmation-dialog';
|
||||||
import UserLink from '../user-link';
|
import UserLink from '../user-link';
|
||||||
|
import UsersFilterBar from './users-filter-bar';
|
||||||
|
|
||||||
const { availableRoles, availableAdminRoles, institutions } = window.sysadmin.pageOptions;
|
const { availableRoles, availableAdminRoles, institutions } = window.sysadmin.pageOptions;
|
||||||
|
|
||||||
@@ -39,11 +40,11 @@ class Content extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getPreviousPage = () => {
|
getPreviousPage = () => {
|
||||||
this.props.getListByPage(this.props.currentPage - 1);
|
this.props.getListByPage(this.props.currentPage - 1, this.props.is_active, this.props.role);
|
||||||
};
|
};
|
||||||
|
|
||||||
getNextPage = () => {
|
getNextPage = () => {
|
||||||
this.props.getListByPage(this.props.currentPage + 1);
|
this.props.getListByPage(this.props.currentPage + 1, this.props.is_active, this.props.role);
|
||||||
};
|
};
|
||||||
|
|
||||||
sortByQuotaUsage = (e) => {
|
sortByQuotaUsage = (e) => {
|
||||||
@@ -57,6 +58,7 @@ class Content extends Component {
|
|||||||
curPerPage, hasNextPage, currentPage,
|
curPerPage, hasNextPage, currentPage,
|
||||||
sortBy, sortOrder
|
sortBy, sortOrder
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Loading />;
|
return <Loading />;
|
||||||
} else if (errorMsg) {
|
} else if (errorMsg) {
|
||||||
@@ -129,21 +131,26 @@ class Content extends Component {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{items.map((item, index) => {
|
{items.map((item, index) => {
|
||||||
return (<Item
|
if (index < this.props.curPerPage) {
|
||||||
key={index}
|
return (
|
||||||
item={item}
|
<Item
|
||||||
isItemFreezed={this.state.isItemFreezed}
|
key={index}
|
||||||
onFreezedItem={this.onFreezedItem}
|
item={item}
|
||||||
onUnfreezedItem={this.onUnfreezedItem}
|
isItemFreezed={this.state.isItemFreezed}
|
||||||
toggleItemFreezed={this.toggleItemFreezed}
|
onFreezedItem={this.onFreezedItem}
|
||||||
updateUser={this.props.updateUser}
|
onUnfreezedItem={this.onUnfreezedItem}
|
||||||
deleteUser={this.props.deleteUser}
|
toggleItemFreezed={this.toggleItemFreezed}
|
||||||
updateAdminRole={this.props.updateAdminRole}
|
updateUser={this.props.updateUser}
|
||||||
revokeAdmin={this.props.revokeAdmin}
|
deleteUser={this.props.deleteUser}
|
||||||
onUserSelected={this.props.onUserSelected}
|
updateAdminRole={this.props.updateAdminRole}
|
||||||
isAdmin={this.props.isAdmin}
|
revokeAdmin={this.props.revokeAdmin}
|
||||||
isLDAPImported={this.props.isLDAPImported}
|
onUserSelected={this.props.onUserSelected}
|
||||||
/>);
|
isAdmin={this.props.isAdmin}
|
||||||
|
isLDAPImported={this.props.isLDAPImported}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -160,7 +167,19 @@ class Content extends Component {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
return items.length ? table : emptyTip;
|
return (
|
||||||
|
<div>
|
||||||
|
{this.props.currentItem === 'database' &&
|
||||||
|
<UsersFilterBar
|
||||||
|
isActive={this.props.is_active}
|
||||||
|
role={this.props.role}
|
||||||
|
onStatusChange={this.props.onStatusChange}
|
||||||
|
onRoleChange={this.props.onRoleChange}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
{items.length ? table : emptyTip}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,6 +207,11 @@ Content.propTypes = {
|
|||||||
curPerPage: PropTypes.number,
|
curPerPage: PropTypes.number,
|
||||||
hasNextPage: PropTypes.bool,
|
hasNextPage: PropTypes.bool,
|
||||||
sortOrder: PropTypes.string,
|
sortOrder: PropTypes.string,
|
||||||
|
is_active: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
role: PropTypes.string,
|
||||||
|
currentItem: PropTypes.string,
|
||||||
|
onStatusChange: PropTypes.func,
|
||||||
|
onRoleChange: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item extends Component {
|
class Item extends Component {
|
||||||
|
35
frontend/src/pages/sys-admin/users/users-filter-bar.css
Normal file
35
frontend/src/pages/sys-admin/users/users-filter-bar.css
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
.users-filter-bar .users-filter-bar-dropdown-toggle {
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding-left: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.users-filter-bar .users-filter-bar-dropdown-toggle .sf3-font-drop-down {
|
||||||
|
color: #999;
|
||||||
|
margin-left: auto;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
transform: scale(.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.users-filter-bar .users-filter-bar-dropdown-toggle:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.users-filter-bar .dropdown-menu .dropdown-item {
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.users-filter-bar .dropdown-menu .dropdown-item:hover .sf2-icon-tick,
|
||||||
|
.users-filter-bar .dropdown-menu .dropdown-item:focus .sf2-icon-tick {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
121
frontend/src/pages/sys-admin/users/users-filter-bar.js
Normal file
121
frontend/src/pages/sys-admin/users/users-filter-bar.js
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Dropdown, DropdownToggle, DropdownItem, DropdownMenu } from 'reactstrap';
|
||||||
|
import { gettext } from '../../../utils/constants';
|
||||||
|
import './users-filter-bar.css';
|
||||||
|
|
||||||
|
const { availableRoles } = window.sysadmin.pageOptions;
|
||||||
|
|
||||||
|
class UsersFilterBar extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
isStatusOpen: false,
|
||||||
|
isRoleOpen: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
translateStatus = (status) => {
|
||||||
|
switch (status) {
|
||||||
|
case '0':
|
||||||
|
return gettext('Inactive');
|
||||||
|
case '1':
|
||||||
|
return gettext('Active');
|
||||||
|
default:
|
||||||
|
return gettext('All');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
translateRole = (role) => {
|
||||||
|
switch (role) {
|
||||||
|
case 'default':
|
||||||
|
return gettext('Default');
|
||||||
|
case 'guest':
|
||||||
|
return gettext('Guest');
|
||||||
|
default:
|
||||||
|
return gettext('All');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
toggleStatusDropdown = () => {
|
||||||
|
this.setState({ isStatusOpen: !this.state.isStatusOpen });
|
||||||
|
};
|
||||||
|
|
||||||
|
toggleRoleDropdown = () => {
|
||||||
|
this.setState({ isRoleOpen: !this.state.isRoleOpen });
|
||||||
|
};
|
||||||
|
|
||||||
|
renderCheck = () => {
|
||||||
|
return <span className="sf2-icon-tick text-gray font-weight-bold"></span>;
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { onStatusChange, onRoleChange } = this.props;
|
||||||
|
return (
|
||||||
|
<div className="users-filter-bar mt-4 mb-2 d-flex">
|
||||||
|
<Dropdown isOpen={this.state.isStatusOpen} toggle={this.toggleStatusDropdown}>
|
||||||
|
<DropdownToggle
|
||||||
|
tag="div"
|
||||||
|
data-toggle="dropdown"
|
||||||
|
aria-expanded={this.state.isStatusOpen}
|
||||||
|
className="users-filter-bar-dropdown-toggle"
|
||||||
|
>
|
||||||
|
<span>{gettext('Status')}{': '}{this.translateStatus(this.props.isActive)}</span>
|
||||||
|
<span className='sf3-font-drop-down sf3-font'></span>
|
||||||
|
</DropdownToggle>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownItem key={0} onClick={() => { onStatusChange(''); }}>
|
||||||
|
<span>{gettext('All')}</span>{this.props.isActive === '' && this.renderCheck()}
|
||||||
|
</DropdownItem>
|
||||||
|
<DropdownItem key={1} onClick={() => { onStatusChange('1'); }}>
|
||||||
|
<span>{gettext('Active')}</span>{this.props.isActive === '1' && this.renderCheck()}
|
||||||
|
</DropdownItem>
|
||||||
|
<DropdownItem key={2} onClick={() => { onStatusChange('0'); }}>
|
||||||
|
<span>{gettext('Inactive')}</span>{this.props.isActive === '0' && this.renderCheck()}
|
||||||
|
</DropdownItem>
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
|
<Dropdown isOpen={this.state.isRoleOpen} toggle={this.toggleRoleDropdown}>
|
||||||
|
<DropdownToggle
|
||||||
|
tag="div"
|
||||||
|
data-toggle="dropdown"
|
||||||
|
aria-expanded={this.state.isRoleOpen}
|
||||||
|
className="users-filter-bar-dropdown-toggle"
|
||||||
|
>
|
||||||
|
<span>{gettext('Role')}{': '}{this.translateRole(this.props.role)}</span>
|
||||||
|
<span className='sf3-font-drop-down sf3-font'></span>
|
||||||
|
</DropdownToggle>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownItem key={0} onClick={() => { onRoleChange(''); }}>
|
||||||
|
<span>{gettext('All')}</span>
|
||||||
|
{this.props.role === '' && this.renderCheck()}
|
||||||
|
</DropdownItem>
|
||||||
|
{availableRoles.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<DropdownItem key={index} onClick={() => { onRoleChange(item); }}>
|
||||||
|
<span>{this.translateRole(item)}</span>
|
||||||
|
{this.props.role === item && this.renderCheck()}
|
||||||
|
</DropdownItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UsersFilterBar.propTypes = {
|
||||||
|
loading: PropTypes.bool,
|
||||||
|
curPerPage: PropTypes.number,
|
||||||
|
sortBy: PropTypes.string,
|
||||||
|
currentPage: PropTypes.number,
|
||||||
|
sortOrder: PropTypes.string,
|
||||||
|
onStatusChange: PropTypes.func,
|
||||||
|
onRoleChange: PropTypes.func,
|
||||||
|
role: PropTypes.string,
|
||||||
|
isActive: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UsersFilterBar;
|
@@ -4,6 +4,7 @@ import { Button } from 'reactstrap';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Utils } from '../../../utils/utils';
|
import { Utils } from '../../../utils/utils';
|
||||||
import { seafileAPI } from '../../../utils/seafile-api';
|
import { seafileAPI } from '../../../utils/seafile-api';
|
||||||
|
import { systemAdminAPI } from '../../../utils/system-admin-api';
|
||||||
import { isPro, gettext, siteRoot } from '../../../utils/constants';
|
import { isPro, gettext, siteRoot } from '../../../utils/constants';
|
||||||
import toaster from '../../../components/toast';
|
import toaster from '../../../components/toast';
|
||||||
import SysAdminUserSetQuotaDialog from '../../../components/dialog/sysadmin-dialog/set-quota';
|
import SysAdminUserSetQuotaDialog from '../../../components/dialog/sysadmin-dialog/set-quota';
|
||||||
@@ -43,7 +44,9 @@ class Users extends Component {
|
|||||||
isAddUserDialogOpen: false,
|
isAddUserDialogOpen: false,
|
||||||
isBatchSetQuotaDialogOpen: false,
|
isBatchSetQuotaDialogOpen: false,
|
||||||
isBatchDeleteUserDialogOpen: false,
|
isBatchDeleteUserDialogOpen: false,
|
||||||
isBatchAddAdminDialogOpen: false
|
isBatchAddAdminDialogOpen: false,
|
||||||
|
is_active: null,
|
||||||
|
role: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,15 +58,17 @@ class Users extends Component {
|
|||||||
const {
|
const {
|
||||||
currentPage, perPage,
|
currentPage, perPage,
|
||||||
sortBy = '',
|
sortBy = '',
|
||||||
sortOrder = 'asc'
|
sortOrder = 'asc',
|
||||||
|
is_active,
|
||||||
|
role,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
this.setState({
|
this.setState({
|
||||||
perPage: parseInt(urlParams.get('per_page') || perPage),
|
perPage: parseInt(urlParams.get('per_page') || perPage),
|
||||||
currentPage: parseInt(urlParams.get('page') || currentPage),
|
currentPage: parseInt(urlParams.get('page') || currentPage),
|
||||||
sortBy: urlParams.get('order_by') || sortBy,
|
sortBy: urlParams.get('order_by') || sortBy,
|
||||||
sortOrder: urlParams.get('direction') || sortOrder
|
sortOrder: urlParams.get('direction') || sortOrder,
|
||||||
}, () => {
|
}, () => {
|
||||||
this.getUsersListByPage(this.state.currentPage);
|
this.getUsersListByPage(this.state.currentPage, is_active, role);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,10 +165,10 @@ class Users extends Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
getUsersListByPage = (page) => {
|
getUsersListByPage = (page, is_active, role) => {
|
||||||
const { perPage, sortBy, sortOrder } = this.state;
|
const { perPage, sortBy, sortOrder } = this.state;
|
||||||
const { isLDAPImported } = this.props;
|
const { isLDAPImported } = this.props;
|
||||||
seafileAPI.sysAdminListUsers(page, perPage, isLDAPImported, sortBy, sortOrder).then(res => {
|
systemAdminAPI.sysAdminListUsers(page, perPage, isLDAPImported, sortBy, sortOrder, is_active, role).then(res => {
|
||||||
let users = res.data.data.map(user => {return new SysAdminUser(user);});
|
let users = res.data.data.map(user => {return new SysAdminUser(user);});
|
||||||
this.setState({
|
this.setState({
|
||||||
userList: users,
|
userList: users,
|
||||||
@@ -179,6 +184,39 @@ class Users extends Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
updateURL = (page, perPage) => {
|
||||||
|
let url = new URL(location.href);
|
||||||
|
let searchParams = new URLSearchParams(url.search);
|
||||||
|
searchParams.set('page', page);
|
||||||
|
searchParams.set('per_page', perPage);
|
||||||
|
url.search = searchParams.toString();
|
||||||
|
navigate(url.toString());
|
||||||
|
};
|
||||||
|
|
||||||
|
// is_active: '1', '0', '' (active, inactive, all)
|
||||||
|
onStatusChange = (is_active) => {
|
||||||
|
this.setState({
|
||||||
|
is_active: is_active,
|
||||||
|
currentPage: 1
|
||||||
|
}, () => {
|
||||||
|
const { currentPage, perPage, is_active, role } = this.state;
|
||||||
|
this.updateURL(currentPage, perPage);
|
||||||
|
this.getUsersListByPage(currentPage, is_active, role);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// role: 'default', 'guest', ''
|
||||||
|
onRoleChange = (role) => {
|
||||||
|
this.setState({
|
||||||
|
role: role,
|
||||||
|
currentPage: 1
|
||||||
|
}, () => {
|
||||||
|
const { currentPage,perPage, is_active, role } = this.state;
|
||||||
|
this.updateURL(currentPage, perPage);
|
||||||
|
this.getUsersListByPage(currentPage, is_active, role);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
sortByQuotaUsage = () => {
|
sortByQuotaUsage = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
sortBy: 'quota_usage',
|
sortBy: 'quota_usage',
|
||||||
@@ -187,13 +225,13 @@ class Users extends Component {
|
|||||||
}, () => {
|
}, () => {
|
||||||
let url = new URL(location.href);
|
let url = new URL(location.href);
|
||||||
let searchParams = new URLSearchParams(url.search);
|
let searchParams = new URLSearchParams(url.search);
|
||||||
const { currentPage, sortBy, sortOrder } = this.state;
|
const { currentPage, sortBy, sortOrder, is_active, role } = this.state;
|
||||||
searchParams.set('page', currentPage);
|
searchParams.set('page', currentPage);
|
||||||
searchParams.set('order_by', sortBy);
|
searchParams.set('order_by', sortBy);
|
||||||
searchParams.set('direction', sortOrder);
|
searchParams.set('direction', sortOrder);
|
||||||
url.search = searchParams.toString();
|
url.search = searchParams.toString();
|
||||||
navigate(url.toString());
|
navigate(url.toString());
|
||||||
this.getUsersListByPage(currentPage);
|
this.getUsersListByPage(currentPage, is_active, role);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -309,7 +347,7 @@ class Users extends Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
perPage: perPage
|
perPage: perPage
|
||||||
}, () => {
|
}, () => {
|
||||||
this.getUsersListByPage(1);
|
this.getUsersListByPage(1, this.state.is_active, this.state.role);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -468,6 +506,8 @@ class Users extends Component {
|
|||||||
currentPage={this.state.currentPage}
|
currentPage={this.state.currentPage}
|
||||||
hasNextPage={this.state.hasNextPage}
|
hasNextPage={this.state.hasNextPage}
|
||||||
curPerPage={this.state.perPage}
|
curPerPage={this.state.perPage}
|
||||||
|
is_active={this.state.is_active}
|
||||||
|
role={this.state.role}
|
||||||
resetPerPage={this.resetPerPage}
|
resetPerPage={this.resetPerPage}
|
||||||
getListByPage={this.getUsersListByPage}
|
getListByPage={this.getUsersListByPage}
|
||||||
updateUser={this.updateUser}
|
updateUser={this.updateUser}
|
||||||
@@ -477,6 +517,9 @@ class Users extends Component {
|
|||||||
onUserSelected={this.onUserSelected}
|
onUserSelected={this.onUserSelected}
|
||||||
isAllUsersSelected={this.isAllUsersSelected}
|
isAllUsersSelected={this.isAllUsersSelected}
|
||||||
toggleSelectAllUsers={this.toggleSelectAllUsers}
|
toggleSelectAllUsers={this.toggleSelectAllUsers}
|
||||||
|
onRoleChange={this.onRoleChange}
|
||||||
|
onStatusChange={this.onStatusChange}
|
||||||
|
currentItem={this.getCurrentNavItem()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
75
frontend/src/utils/system-admin-api.js
Normal file
75
frontend/src/utils/system-admin-api.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import cookie from 'react-cookies';
|
||||||
|
import { siteRoot } from './constants';
|
||||||
|
|
||||||
|
class SystemAdminAPI {
|
||||||
|
|
||||||
|
init({ server, username, password, token }) {
|
||||||
|
this.server = server;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.token = token; //none
|
||||||
|
if (this.token && this.server) {
|
||||||
|
this.req = axios.create({
|
||||||
|
baseURL: this.server,
|
||||||
|
headers: { 'Authorization': 'Token ' + this.token },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
initForSeahubUsage({ siteRoot, xcsrfHeaders }) {
|
||||||
|
if (siteRoot && siteRoot.charAt(siteRoot.length-1) === '/') {
|
||||||
|
var server = siteRoot.substring(0, siteRoot.length-1);
|
||||||
|
this.server = server;
|
||||||
|
} else {
|
||||||
|
this.server = siteRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.req = axios.create({
|
||||||
|
headers: {
|
||||||
|
'X-CSRFToken': xcsrfHeaders,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
_sendPostRequest(url, form) {
|
||||||
|
if (form.getHeaders) {
|
||||||
|
return this.req.post(url, form, {
|
||||||
|
headers:form.getHeaders()
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return this.req.post(url, form);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sysAdminListUsers(page, perPage, isLDAPImported, sortBy, sortOrder, is_active, role) {
|
||||||
|
let url = this.server + '/api/v2.1/admin/users/';
|
||||||
|
let params = {
|
||||||
|
page: page,
|
||||||
|
per_page: perPage,
|
||||||
|
};
|
||||||
|
if (is_active) {
|
||||||
|
params.is_active = is_active;
|
||||||
|
}
|
||||||
|
if (role) {
|
||||||
|
params.role = role;
|
||||||
|
}
|
||||||
|
if (isLDAPImported) {
|
||||||
|
params.source = 'LDAPImport';
|
||||||
|
}
|
||||||
|
if (sortBy) {
|
||||||
|
params.order_by = sortBy;
|
||||||
|
params.direction = sortOrder;
|
||||||
|
}
|
||||||
|
return this.req.get(url, {params: params});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let systemAdminAPI = new SystemAdminAPI();
|
||||||
|
let xcsrfHeaders = cookie.load('sfcsrftoken');
|
||||||
|
systemAdminAPI.initForSeahubUsage({ siteRoot, xcsrfHeaders });
|
||||||
|
|
||||||
|
export { systemAdminAPI };
|
@@ -46,6 +46,7 @@ from seahub.utils.timeutils import timestamp_to_isoformat_timestr, \
|
|||||||
datetime_to_isoformat_timestr
|
datetime_to_isoformat_timestr
|
||||||
from seahub.utils.user_permissions import get_user_role
|
from seahub.utils.user_permissions import get_user_role
|
||||||
from seahub.utils.repo import normalize_repo_status_code
|
from seahub.utils.repo import normalize_repo_status_code
|
||||||
|
from seahub.utils.ccnet_db import CcnetDB
|
||||||
from seahub.constants import DEFAULT_ADMIN
|
from seahub.constants import DEFAULT_ADMIN
|
||||||
from seahub.role_permissions.models import AdminRole
|
from seahub.role_permissions.models import AdminRole
|
||||||
from seahub.role_permissions.utils import get_available_roles
|
from seahub.role_permissions.utils import get_available_roles
|
||||||
@@ -549,7 +550,7 @@ class AdminUsers(APIView):
|
|||||||
throttle_classes = (UserRateThrottle, )
|
throttle_classes = (UserRateThrottle, )
|
||||||
|
|
||||||
def get_info_of_users_order_by_quota_usage(self, source, direction,
|
def get_info_of_users_order_by_quota_usage(self, source, direction,
|
||||||
page, per_page):
|
page, per_page, is_active=None, role=None):
|
||||||
|
|
||||||
# get user's quota usage info
|
# get user's quota usage info
|
||||||
user_usage_dict = {}
|
user_usage_dict = {}
|
||||||
@@ -581,6 +582,13 @@ class AdminUsers(APIView):
|
|||||||
# sort
|
# sort
|
||||||
users.sort(key=lambda item: item.quota_usage,
|
users.sort(key=lambda item: item.quota_usage,
|
||||||
reverse=direction == 'desc')
|
reverse=direction == 'desc')
|
||||||
|
if is_active == '1':
|
||||||
|
users = [u for u in users if u.is_active]
|
||||||
|
elif is_active == '0':
|
||||||
|
users = [u for u in users if not u.is_active]
|
||||||
|
|
||||||
|
if role:
|
||||||
|
users = [u for u in users if get_user_role(u) == role]
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
MULTI_INSTITUTION = getattr(settings, 'MULTI_INSTITUTION', False)
|
MULTI_INSTITUTION = getattr(settings, 'MULTI_INSTITUTION', False)
|
||||||
@@ -633,12 +641,15 @@ class AdminUsers(APIView):
|
|||||||
try:
|
try:
|
||||||
page = int(request.GET.get('page', '1'))
|
page = int(request.GET.get('page', '1'))
|
||||||
per_page = int(request.GET.get('per_page', '25'))
|
per_page = int(request.GET.get('per_page', '25'))
|
||||||
|
is_active = request.GET.get('is_active', None)
|
||||||
|
role = request.GET.get('role', None)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
page = 1
|
page = 1
|
||||||
per_page = 25
|
per_page = 25
|
||||||
|
is_active, role = None, None
|
||||||
|
|
||||||
start = (page - 1) * per_page
|
start = (page - 1) * per_page
|
||||||
|
limit = per_page + 1
|
||||||
source = request.GET.get('source', 'DB').lower().strip()
|
source = request.GET.get('source', 'DB').lower().strip()
|
||||||
if source not in ['db', 'ldapimport']:
|
if source not in ['db', 'ldapimport']:
|
||||||
# source: 'DB' or 'LDAPImport', default is 'DB'
|
# source: 'DB' or 'LDAPImport', default is 'DB'
|
||||||
@@ -671,7 +682,10 @@ class AdminUsers(APIView):
|
|||||||
data = self.get_info_of_users_order_by_quota_usage(source,
|
data = self.get_info_of_users_order_by_quota_usage(source,
|
||||||
direction,
|
direction,
|
||||||
page,
|
page,
|
||||||
per_page)
|
per_page,
|
||||||
|
is_active,
|
||||||
|
role,
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
error_msg = 'Internal Server Error'
|
error_msg = 'Internal Server Error'
|
||||||
@@ -680,7 +694,11 @@ class AdminUsers(APIView):
|
|||||||
result = {'data': data, 'total_count': total_count}
|
result = {'data': data, 'total_count': total_count}
|
||||||
return Response(result)
|
return Response(result)
|
||||||
else:
|
else:
|
||||||
users = ccnet_api.get_emailusers('DB', start, per_page)
|
try:
|
||||||
|
ccnet_db = CcnetDB()
|
||||||
|
users, total_count = ccnet_db.list_eligible_users(start, limit, is_active, role)
|
||||||
|
except Exception:
|
||||||
|
users = ccnet_api.get_emailusers('DB', start, per_page)
|
||||||
|
|
||||||
elif source == 'ldapimport':
|
elif source == 'ldapimport':
|
||||||
ldap_users_count = multi_ldap_users_count = 0
|
ldap_users_count = multi_ldap_users_count = 0
|
||||||
|
@@ -28,8 +28,9 @@ import os
|
|||||||
import configparser
|
import configparser
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
|
|
||||||
|
|
||||||
class CcnetGroup(object):
|
class CcnetGroup(object):
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.id = kwargs.get('group_id')
|
self.id = kwargs.get('group_id')
|
||||||
self.group_name = kwargs.get('group_name')
|
self.group_name = kwargs.get('group_name')
|
||||||
@@ -37,13 +38,25 @@ class CcnetGroup(object):
|
|||||||
self.timestamp = kwargs.get('timestamp')
|
self.timestamp = kwargs.get('timestamp')
|
||||||
self.parent_group_id = kwargs.get('parent_group_id')
|
self.parent_group_id = kwargs.get('parent_group_id')
|
||||||
|
|
||||||
|
|
||||||
|
class CcnetUsers(object):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self.user_id = kwargs.get('user_id')
|
||||||
|
self.email = kwargs.get('email')
|
||||||
|
self.is_staff = kwargs.get('is_staff')
|
||||||
|
self.is_active = kwargs.get('is_active')
|
||||||
|
self.ctime = kwargs.get('ctime')
|
||||||
|
self.role = kwargs.get('role')
|
||||||
|
self.passwd = kwargs.get('passwd')
|
||||||
|
|
||||||
|
|
||||||
class CcnetDB:
|
class CcnetDB:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.db_name = get_ccnet_db_name()[0]
|
self.db_name = get_ccnet_db_name()[0]
|
||||||
|
|
||||||
|
|
||||||
def list_org_departments(self, org_id):
|
def list_org_departments(self, org_id):
|
||||||
sql = f"""
|
sql = f"""
|
||||||
SELECT
|
SELECT
|
||||||
@@ -63,10 +76,10 @@ class CcnetDB:
|
|||||||
group_id = item[0]
|
group_id = item[0]
|
||||||
group_name = item[1]
|
group_name = item[1]
|
||||||
creator_name = item[2]
|
creator_name = item[2]
|
||||||
timestamp=item[3]
|
timestamp = item[3]
|
||||||
parent_group_id = item[5]
|
parent_group_id = item[5]
|
||||||
params = {
|
params = {
|
||||||
'group_id':group_id,
|
'group_id': group_id,
|
||||||
'group_name': group_name,
|
'group_name': group_name,
|
||||||
'creator_name': creator_name,
|
'creator_name': creator_name,
|
||||||
'timestamp': timestamp,
|
'timestamp': timestamp,
|
||||||
@@ -75,3 +88,77 @@ class CcnetDB:
|
|||||||
group_obj = CcnetGroup(**params)
|
group_obj = CcnetGroup(**params)
|
||||||
groups.append(group_obj)
|
groups.append(group_obj)
|
||||||
return groups
|
return groups
|
||||||
|
|
||||||
|
def list_eligible_users(self, start, limit, is_active=None, role=None):
|
||||||
|
|
||||||
|
def status(is_active):
|
||||||
|
return 'AND t1.is_active=%s ' % is_active
|
||||||
|
|
||||||
|
def is_role(role):
|
||||||
|
if role == 'default':
|
||||||
|
return 'AND (t2.role is null or t2.role = "default")'
|
||||||
|
else:
|
||||||
|
return 'AND t2.role = "%s"' % role
|
||||||
|
|
||||||
|
search_clause = ''
|
||||||
|
if is_active:
|
||||||
|
search_clause += status(is_active)
|
||||||
|
if role:
|
||||||
|
search_clause += is_role(role)
|
||||||
|
|
||||||
|
count_sql = f"""
|
||||||
|
SELECT count(1)
|
||||||
|
FROM
|
||||||
|
`{self.db_name}`.`EmailUser` t1
|
||||||
|
LEFT JOIN
|
||||||
|
`{self.db_name}`.`UserRole` t2
|
||||||
|
ON
|
||||||
|
t1.email = t2.email
|
||||||
|
WHERE
|
||||||
|
t1.email NOT LIKE '%%@seafile_group' %s
|
||||||
|
ORDER BY t1.id
|
||||||
|
""" % search_clause
|
||||||
|
|
||||||
|
sql = f"""
|
||||||
|
SELECT t1.id, t1.email, t1.is_staff, t1.is_active, t1.ctime, t2.role, t1.passwd
|
||||||
|
FROM
|
||||||
|
`{self.db_name}`.`EmailUser` t1
|
||||||
|
LEFT JOIN
|
||||||
|
`{self.db_name}`.`UserRole` t2
|
||||||
|
ON
|
||||||
|
t1.email = t2.email
|
||||||
|
WHERE
|
||||||
|
t1.email NOT LIKE '%%@seafile_group' %s
|
||||||
|
ORDER BY t1.id
|
||||||
|
LIMIT {limit} OFFSET {start}
|
||||||
|
""" % search_clause
|
||||||
|
|
||||||
|
users = []
|
||||||
|
total = 0
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute(count_sql)
|
||||||
|
cursor.execute(count_sql)
|
||||||
|
total_count = int(cursor.fetchone()[0])
|
||||||
|
|
||||||
|
cursor.execute(sql)
|
||||||
|
for item in cursor.fetchall():
|
||||||
|
user_id = item[0]
|
||||||
|
email = item[1]
|
||||||
|
is_staff = item[2]
|
||||||
|
is_active = item[3]
|
||||||
|
ctime = item[4]
|
||||||
|
role = item[5]
|
||||||
|
passwd = item[6]
|
||||||
|
params = {
|
||||||
|
'user_id': user_id,
|
||||||
|
'email': email,
|
||||||
|
'is_staff': is_staff,
|
||||||
|
'is_active': is_active,
|
||||||
|
'ctime': ctime,
|
||||||
|
'role': role,
|
||||||
|
'passwd': passwd
|
||||||
|
}
|
||||||
|
users_obj = CcnetUsers(**params)
|
||||||
|
users.append(users_obj)
|
||||||
|
|
||||||
|
return users, total_count
|
||||||
|
Reference in New Issue
Block a user