mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-08 10:22:46 +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 CommonOperationConfirmationDialog from '../../../components/dialog/common-operation-confirmation-dialog';
|
||||
import UserLink from '../user-link';
|
||||
import UsersFilterBar from './users-filter-bar';
|
||||
|
||||
const { availableRoles, availableAdminRoles, institutions } = window.sysadmin.pageOptions;
|
||||
|
||||
@@ -39,11 +40,11 @@ class Content extends Component {
|
||||
};
|
||||
|
||||
getPreviousPage = () => {
|
||||
this.props.getListByPage(this.props.currentPage - 1);
|
||||
this.props.getListByPage(this.props.currentPage - 1, this.props.is_active, this.props.role);
|
||||
};
|
||||
|
||||
getNextPage = () => {
|
||||
this.props.getListByPage(this.props.currentPage + 1);
|
||||
this.props.getListByPage(this.props.currentPage + 1, this.props.is_active, this.props.role);
|
||||
};
|
||||
|
||||
sortByQuotaUsage = (e) => {
|
||||
@@ -57,6 +58,7 @@ class Content extends Component {
|
||||
curPerPage, hasNextPage, currentPage,
|
||||
sortBy, sortOrder
|
||||
} = this.props;
|
||||
|
||||
if (loading) {
|
||||
return <Loading />;
|
||||
} else if (errorMsg) {
|
||||
@@ -129,7 +131,9 @@ class Content extends Component {
|
||||
</thead>
|
||||
<tbody>
|
||||
{items.map((item, index) => {
|
||||
return (<Item
|
||||
if (index < this.props.curPerPage) {
|
||||
return (
|
||||
<Item
|
||||
key={index}
|
||||
item={item}
|
||||
isItemFreezed={this.state.isItemFreezed}
|
||||
@@ -143,7 +147,10 @@ class Content extends Component {
|
||||
onUserSelected={this.props.onUserSelected}
|
||||
isAdmin={this.props.isAdmin}
|
||||
isLDAPImported={this.props.isLDAPImported}
|
||||
/>);
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -160,7 +167,19 @@ class Content extends Component {
|
||||
</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,
|
||||
hasNextPage: PropTypes.bool,
|
||||
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 {
|
||||
|
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 { Utils } from '../../../utils/utils';
|
||||
import { seafileAPI } from '../../../utils/seafile-api';
|
||||
import { systemAdminAPI } from '../../../utils/system-admin-api';
|
||||
import { isPro, gettext, siteRoot } from '../../../utils/constants';
|
||||
import toaster from '../../../components/toast';
|
||||
import SysAdminUserSetQuotaDialog from '../../../components/dialog/sysadmin-dialog/set-quota';
|
||||
@@ -43,7 +44,9 @@ class Users extends Component {
|
||||
isAddUserDialogOpen: false,
|
||||
isBatchSetQuotaDialogOpen: false,
|
||||
isBatchDeleteUserDialogOpen: false,
|
||||
isBatchAddAdminDialogOpen: false
|
||||
isBatchAddAdminDialogOpen: false,
|
||||
is_active: null,
|
||||
role: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -55,15 +58,17 @@ class Users extends Component {
|
||||
const {
|
||||
currentPage, perPage,
|
||||
sortBy = '',
|
||||
sortOrder = 'asc'
|
||||
sortOrder = 'asc',
|
||||
is_active,
|
||||
role,
|
||||
} = this.state;
|
||||
this.setState({
|
||||
perPage: parseInt(urlParams.get('per_page') || perPage),
|
||||
currentPage: parseInt(urlParams.get('page') || currentPage),
|
||||
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 { 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);});
|
||||
this.setState({
|
||||
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 = () => {
|
||||
this.setState({
|
||||
sortBy: 'quota_usage',
|
||||
@@ -187,13 +225,13 @@ class Users extends Component {
|
||||
}, () => {
|
||||
let url = new URL(location.href);
|
||||
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('order_by', sortBy);
|
||||
searchParams.set('direction', sortOrder);
|
||||
url.search = searchParams.toString();
|
||||
navigate(url.toString());
|
||||
this.getUsersListByPage(currentPage);
|
||||
this.getUsersListByPage(currentPage, is_active, role);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -309,7 +347,7 @@ class Users extends Component {
|
||||
this.setState({
|
||||
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}
|
||||
hasNextPage={this.state.hasNextPage}
|
||||
curPerPage={this.state.perPage}
|
||||
is_active={this.state.is_active}
|
||||
role={this.state.role}
|
||||
resetPerPage={this.resetPerPage}
|
||||
getListByPage={this.getUsersListByPage}
|
||||
updateUser={this.updateUser}
|
||||
@@ -477,6 +517,9 @@ class Users extends Component {
|
||||
onUserSelected={this.onUserSelected}
|
||||
isAllUsersSelected={this.isAllUsersSelected}
|
||||
toggleSelectAllUsers={this.toggleSelectAllUsers}
|
||||
onRoleChange={this.onRoleChange}
|
||||
onStatusChange={this.onStatusChange}
|
||||
currentItem={this.getCurrentNavItem()}
|
||||
/>
|
||||
</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
|
||||
from seahub.utils.user_permissions import get_user_role
|
||||
from seahub.utils.repo import normalize_repo_status_code
|
||||
from seahub.utils.ccnet_db import CcnetDB
|
||||
from seahub.constants import DEFAULT_ADMIN
|
||||
from seahub.role_permissions.models import AdminRole
|
||||
from seahub.role_permissions.utils import get_available_roles
|
||||
@@ -549,7 +550,7 @@ class AdminUsers(APIView):
|
||||
throttle_classes = (UserRateThrottle, )
|
||||
|
||||
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
|
||||
user_usage_dict = {}
|
||||
@@ -581,6 +582,13 @@ class AdminUsers(APIView):
|
||||
# sort
|
||||
users.sort(key=lambda item: item.quota_usage,
|
||||
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 = []
|
||||
MULTI_INSTITUTION = getattr(settings, 'MULTI_INSTITUTION', False)
|
||||
@@ -633,12 +641,15 @@ class AdminUsers(APIView):
|
||||
try:
|
||||
page = int(request.GET.get('page', '1'))
|
||||
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:
|
||||
page = 1
|
||||
per_page = 25
|
||||
is_active, role = None, None
|
||||
|
||||
start = (page - 1) * per_page
|
||||
|
||||
limit = per_page + 1
|
||||
source = request.GET.get('source', 'DB').lower().strip()
|
||||
if source not in ['db', 'ldapimport']:
|
||||
# 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,
|
||||
direction,
|
||||
page,
|
||||
per_page)
|
||||
per_page,
|
||||
is_active,
|
||||
role,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
@@ -680,6 +694,10 @@ class AdminUsers(APIView):
|
||||
result = {'data': data, 'total_count': total_count}
|
||||
return Response(result)
|
||||
else:
|
||||
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':
|
||||
|
@@ -28,6 +28,7 @@ import os
|
||||
import configparser
|
||||
from django.db import connection
|
||||
|
||||
|
||||
class CcnetGroup(object):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -37,13 +38,25 @@ class CcnetGroup(object):
|
||||
self.timestamp = kwargs.get('timestamp')
|
||||
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:
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.db_name = get_ccnet_db_name()[0]
|
||||
|
||||
|
||||
def list_org_departments(self, org_id):
|
||||
sql = f"""
|
||||
SELECT
|
||||
@@ -63,10 +76,10 @@ class CcnetDB:
|
||||
group_id = item[0]
|
||||
group_name = item[1]
|
||||
creator_name = item[2]
|
||||
timestamp=item[3]
|
||||
timestamp = item[3]
|
||||
parent_group_id = item[5]
|
||||
params = {
|
||||
'group_id':group_id,
|
||||
'group_id': group_id,
|
||||
'group_name': group_name,
|
||||
'creator_name': creator_name,
|
||||
'timestamp': timestamp,
|
||||
@@ -75,3 +88,77 @@ class CcnetDB:
|
||||
group_obj = CcnetGroup(**params)
|
||||
groups.append(group_obj)
|
||||
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