mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-12 13:24:52 +00:00
Group to department (#6411)
* change group to department * update group quota * admin change group * optimize code * Update change-group-dialog.js * update * code-optimize * code-optimize * Update groups.py * update * fix group-name --------- Co-authored-by: 孙永强 <11704063+s-yongqiang@user.noreply.gitee.com> Co-authored-by: r350178982 <32759763+r350178982@users.noreply.github.com>
This commit is contained in:
49
frontend/src/components/dialog/change-group-dialog.js
Normal file
49
frontend/src/components/dialog/change-group-dialog.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Modal, ModalHeader, ModalFooter, ModalBody } from 'reactstrap';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { gettext } from '../../utils/constants';
|
||||
|
||||
const propTypes = {
|
||||
groupName: PropTypes.string.isRequired,
|
||||
changeGroup2Department: PropTypes.func.isRequired,
|
||||
toggleDialog: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
class ChangeGroupDialog extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selectedOption: null
|
||||
};
|
||||
}
|
||||
|
||||
submit = () => {
|
||||
this.props.changeGroup2Department();
|
||||
this.props.toggleDialog();
|
||||
};
|
||||
|
||||
render() {
|
||||
const groupName = '<span class="op-target">' + Utils.HTMLescape(this.props.groupName) + '</span>';
|
||||
const msg = gettext('Are you sure to change Group {placeholder} to Department ?').replace('{placeholder}', groupName);
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.props.toggleDialog}>
|
||||
<ModalHeader toggle={this.props.toggleDialog}>
|
||||
{gettext('Change group to departmen')}
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
<p dangerouslySetInnerHTML={{ __html: msg }}></p>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="secondary" onClick={this.props.toggleDialog}>{gettext('Cancel')}</Button>
|
||||
<Button color="primary" onClick={this.submit}>{gettext('Submit')}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ChangeGroupDialog.propTypes = propTypes;
|
||||
|
||||
export default ChangeGroupDialog;
|
@@ -8,6 +8,8 @@ import { Utils } from '../../utils/utils';
|
||||
import toaster from '../../components/toast';
|
||||
import OrgGroupInfo from '../../models/org-group';
|
||||
import MainPanelTopbar from './main-panel-topbar';
|
||||
import ChangeGroupDialog from '../../components/dialog/change-group-dialog';
|
||||
import { orgAdminAPI } from '../../utils/org-admin-api';
|
||||
|
||||
class Search extends React.Component {
|
||||
|
||||
@@ -132,6 +134,24 @@ class OrgGroups extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
changeGroupItem = (group) => {
|
||||
orgAdminAPI.orgAdminGroup2Department(orgID, group.id).then(res => {
|
||||
let newGroupList = this.state.orgGroups.map(item => {
|
||||
if (item.id == group.id) {
|
||||
item = new OrgGroupInfo(res.data);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.setState({
|
||||
orgGroups: newGroupList
|
||||
});
|
||||
toaster.success(gettext('Successfully Change the group.'));
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
searchItems = (keyword) => {
|
||||
navigate(`${siteRoot}org/groupadmin/search-groups/?query=${encodeURIComponent(keyword)}`);
|
||||
};
|
||||
@@ -173,6 +193,7 @@ class OrgGroups extends Component {
|
||||
onFreezedItem={this.onFreezedItem}
|
||||
onUnfreezedItem={this.onUnfreezedItem}
|
||||
deleteGroupItem={this.deleteGroupItem}
|
||||
changeGroupItem={this.changeGroupItem}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@@ -197,6 +218,7 @@ const GroupItemPropTypes = {
|
||||
onFreezedItem: PropTypes.func.isRequired,
|
||||
onUnfreezedItem: PropTypes.func.isRequired,
|
||||
deleteGroupItem: PropTypes.func.isRequired,
|
||||
changeGroupItem: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class GroupItem extends React.Component {
|
||||
@@ -206,7 +228,8 @@ class GroupItem extends React.Component {
|
||||
this.state = {
|
||||
highlight: false,
|
||||
showMenu: false,
|
||||
isItemMenuShow: false
|
||||
isItemMenuShow: false,
|
||||
isChangeDialogOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -253,6 +276,16 @@ class GroupItem extends React.Component {
|
||||
toggleDelete = () => {
|
||||
this.props.deleteGroupItem(this.props.group);
|
||||
};
|
||||
toggleChange = () => {
|
||||
this.props.changeGroupItem(this.props.group);
|
||||
};
|
||||
|
||||
toggleChangeDialog = (e) => {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
this.setState({ isChangeDialogOpen: !this.state.isChangeDialogOpen });
|
||||
};
|
||||
|
||||
renderGroupHref = (group) => {
|
||||
let groupInfoHref;
|
||||
@@ -304,11 +337,19 @@ class GroupItem extends React.Component {
|
||||
/>
|
||||
<DropdownMenu>
|
||||
<DropdownItem onClick={this.toggleDelete}>{gettext('Delete')}</DropdownItem>
|
||||
<DropdownItem onClick={this.toggleChangeDialog}>{gettext('Change to department')}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
}
|
||||
{this.state.isChangeDialogOpen &&
|
||||
<ChangeGroupDialog
|
||||
groupName={group.groupName}
|
||||
changeGroup2Department={this.toggleChange}
|
||||
toggleDialog={this.toggleChangeDialog} />
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -10,6 +10,7 @@ import Paginator from '../../../components/paginator';
|
||||
import OpMenu from '../../../components/dialog/op-menu';
|
||||
import CommonOperationConfirmationDialog from '../../../components/dialog/common-operation-confirmation-dialog';
|
||||
import SysAdminTransferGroupDialog from '../../../components/dialog/sysadmin-dialog/sysadmin-group-transfer-dialog';
|
||||
import ChangeGroupDialog from '../../../components/dialog/change-group-dialog';
|
||||
import UserLink from '../user-link';
|
||||
|
||||
class Content extends Component {
|
||||
@@ -70,6 +71,7 @@ class Content extends Component {
|
||||
onUnfreezedItem={this.onUnfreezedItem}
|
||||
deleteGroup={this.props.deleteGroup}
|
||||
transferGroup={this.props.transferGroup}
|
||||
changeGroup2Department={this.props.changeGroup2Department}
|
||||
/>);
|
||||
})}
|
||||
</tbody>
|
||||
@@ -102,6 +104,7 @@ Content.propTypes = {
|
||||
getListByPage: PropTypes.func.isRequired,
|
||||
deleteGroup: PropTypes.func.isRequired,
|
||||
transferGroup: PropTypes.func.isRequired,
|
||||
changeGroup2Department: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class Item extends Component {
|
||||
@@ -112,7 +115,8 @@ class Item extends Component {
|
||||
isOpIconShown: false,
|
||||
highlight: false,
|
||||
isDeleteDialogOpen: false,
|
||||
isTransferDialogOpen: false
|
||||
isTransferDialogOpen: false,
|
||||
isChangeDialogOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -150,6 +154,9 @@ class Item extends Component {
|
||||
case 'Transfer':
|
||||
this.toggleTransferDialog();
|
||||
break;
|
||||
case 'Change':
|
||||
this.toggleChangeDialog();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -169,6 +176,12 @@ class Item extends Component {
|
||||
this.setState({ isTransferDialogOpen: !this.state.isTransferDialogOpen });
|
||||
};
|
||||
|
||||
toggleChangeDialog = (e) => {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
this.setState({ isChangeDialogOpen: !this.state.isChangeDialogOpen });
|
||||
};
|
||||
deleteGroup = () => {
|
||||
this.props.deleteGroup(this.props.item.id);
|
||||
};
|
||||
@@ -177,6 +190,10 @@ class Item extends Component {
|
||||
this.props.transferGroup(this.props.item.id, receiver);
|
||||
};
|
||||
|
||||
changeGroup = () => {
|
||||
this.props.changeGroup2Department(this.props.item.id);
|
||||
};
|
||||
|
||||
translateOperations = (item) => {
|
||||
let translateResult = '';
|
||||
switch (item) {
|
||||
@@ -186,6 +203,9 @@ class Item extends Component {
|
||||
case 'Transfer':
|
||||
translateResult = gettext('Transfer');
|
||||
break;
|
||||
case 'Change':
|
||||
translateResult = gettext('Change to department');
|
||||
break;
|
||||
}
|
||||
|
||||
return translateResult;
|
||||
@@ -193,7 +213,7 @@ class Item extends Component {
|
||||
|
||||
render() {
|
||||
const { item } = this.props;
|
||||
const { isOpIconShown, isDeleteDialogOpen, isTransferDialogOpen } = this.state;
|
||||
const { isOpIconShown, isDeleteDialogOpen, isTransferDialogOpen, isChangeDialogOpen } = this.state;
|
||||
|
||||
let groupName = '<span class="op-target">' + Utils.HTMLescape(item.name) + '</span>';
|
||||
let deleteDialogMsg = gettext('Are you sure you want to delete {placeholder} ?').replace('{placeholder}', groupName);
|
||||
@@ -218,7 +238,7 @@ class Item extends Component {
|
||||
<td>
|
||||
{(isOpIconShown && item.owner != 'system admin') &&
|
||||
<OpMenu
|
||||
operations={['Delete', 'Transfer']}
|
||||
operations={['Delete', 'Transfer', 'Change']}
|
||||
translateOperations={this.translateOperations}
|
||||
onMenuItemClick={this.onMenuItemClick}
|
||||
onFreezedItem={this.props.onFreezedItem}
|
||||
@@ -243,6 +263,13 @@ class Item extends Component {
|
||||
toggleDialog={this.toggleTransferDialog}
|
||||
/>
|
||||
}
|
||||
{isChangeDialogOpen &&
|
||||
<ChangeGroupDialog
|
||||
groupName={item.name}
|
||||
changeGroup2Department={this.changeGroup}
|
||||
toggleDialog={this.toggleChangeDialog}
|
||||
/>
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ import SysAdminCreateGroupDialog from '../../../components/dialog/sysadmin-dialo
|
||||
import MainPanelTopbar from '../main-panel-topbar';
|
||||
import Search from '../search';
|
||||
import Content from './groups-content';
|
||||
import { systemAdminAPI } from '../../../utils/system-admin-api';
|
||||
|
||||
class Groups extends Component {
|
||||
|
||||
@@ -109,6 +110,24 @@ class Groups extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
changeGroup2Department = (groupID) => {
|
||||
systemAdminAPI.adminGroup2Department(groupID).then((res) => {
|
||||
let newGroupList = this.state.groupList.map(item => {
|
||||
if (item.id == groupID) {
|
||||
item = res.data;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.setState({
|
||||
groupList: newGroupList
|
||||
});
|
||||
toaster.success(gettext('Successfully Change the group.'));
|
||||
}).catch((error) => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
getSearch = () => {
|
||||
return <Search
|
||||
placeholder={gettext('Search groups by name')}
|
||||
@@ -144,6 +163,7 @@ class Groups extends Component {
|
||||
pageInfo={this.state.pageInfo}
|
||||
deleteGroup={this.deleteGroup}
|
||||
transferGroup={this.transferGroup}
|
||||
changeGroup2Department={this.changeGroup2Department}
|
||||
getListByPage={this.getGroupListByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
curPerPage={this.state.perPage}
|
||||
|
58
frontend/src/utils/org-admin-api.js
Normal file
58
frontend/src/utils/org-admin-api.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import axios from 'axios';
|
||||
import cookie from 'react-cookies';
|
||||
import { siteRoot } from './constants';
|
||||
|
||||
class OrgAdminAPI {
|
||||
|
||||
init({ server, username, password, token }) {
|
||||
this.server = server;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.token = token;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
orgAdminGroup2Department(orgID, groupID) {
|
||||
var url = this.server + '/api/v2.1/org/' + orgID + '/admin/groups/' + groupID + '/group-to-department/';
|
||||
return this.req.post(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let orgAdminAPI = new OrgAdminAPI();
|
||||
let xcsrfHeaders = cookie.load('sfcsrftoken');
|
||||
orgAdminAPI.initForSeahubUsage({ siteRoot, xcsrfHeaders });
|
||||
|
||||
export { orgAdminAPI };
|
@@ -81,6 +81,11 @@ class SystemAdminAPI {
|
||||
return this.req.get(url);
|
||||
}
|
||||
|
||||
adminGroup2Department(groupID) {
|
||||
const url = this.server + '/api/v2.1/admin/groups/' + groupID + '/group-to-department/';
|
||||
return this.req.post(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let systemAdminAPI = new SystemAdminAPI();
|
||||
|
@@ -26,6 +26,8 @@ from seahub.api2.utils import api_error
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.api2.authentication import TokenAuthentication
|
||||
from seahub.share.models import ExtraGroupsSharePermission
|
||||
from seahub.utils.ccnet_db import CcnetDB
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -398,3 +400,44 @@ class AdminDepartments(APIView):
|
||||
|
||||
return Response(result)
|
||||
|
||||
|
||||
class AdminGroupToDeptView(APIView):
|
||||
"""group to department"""
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAdminUser,)
|
||||
throttle_classes = (UserRateThrottle,)
|
||||
|
||||
def post(self, request, group_id):
|
||||
""" Admin change a group
|
||||
|
||||
group to department
|
||||
|
||||
Permission checking:
|
||||
1. Admin user;
|
||||
"""
|
||||
if not request.user.admin_permissions.can_manage_group():
|
||||
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')
|
||||
|
||||
# recourse check
|
||||
group_id = int(group_id)
|
||||
group = ccnet_api.get_group(group_id)
|
||||
if group.creator_name == 'system admin':
|
||||
error_msg = 'Group %s is already a department' % group_id
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
if not group:
|
||||
error_msg = 'Group %d not found.' % group_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# group to department
|
||||
try:
|
||||
ccnet_db = CcnetDB()
|
||||
ccnet_db.change_groups_into_departments(group_id)
|
||||
seafile_api.set_group_quota(group_id, -2)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
group_info = get_group_info(group_id)
|
||||
return Response(group_info)
|
||||
|
@@ -6,7 +6,7 @@ from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
|
||||
from seaserv import ccnet_api
|
||||
from seaserv import ccnet_api, seafile_api
|
||||
|
||||
from seahub.api2.permissions import IsProVersion, IsOrgAdminUser
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
@@ -18,6 +18,8 @@ from seahub.avatar.templatetags.group_avatar_tags import api_grp_avatar_url, get
|
||||
from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email
|
||||
from seahub.utils.ccnet_db import CcnetDB
|
||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr
|
||||
from seahub.admin_log.signals import admin_operation
|
||||
from seahub.admin_log.models import GROUP_TRANSFER
|
||||
|
||||
from pysearpc import SearpcError
|
||||
|
||||
@@ -247,3 +249,48 @@ class OrgAdminDepartments(APIView):
|
||||
result.append(department_info)
|
||||
|
||||
return Response(result)
|
||||
|
||||
|
||||
class OrgAdminGroupToDeptView(APIView):
|
||||
"""org group to department"""
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsProVersion, IsOrgAdminUser)
|
||||
throttle_classes = (UserRateThrottle,)
|
||||
|
||||
def post(self, request, org_id, group_id):
|
||||
# resource check
|
||||
org_id = int(org_id)
|
||||
if not ccnet_api.get_org_by_id(org_id):
|
||||
error_msg = 'Organization %s not found.' % org_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
group_id = int(group_id)
|
||||
if get_org_id_by_group(group_id) != org_id:
|
||||
error_msg = 'Group %s not found.' % group_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
group = ccnet_api.get_group(group_id)
|
||||
if group.creator_name == 'system admin':
|
||||
error_msg = 'Group %s is already a department' % group_id
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
try:
|
||||
# group to department
|
||||
ccnet_db = CcnetDB()
|
||||
ccnet_db.change_groups_into_departments(group_id)
|
||||
seafile_api.set_group_quota(group_id, -2)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
group = ccnet_api.get_group(group_id)
|
||||
group_info = {
|
||||
"id": group.id,
|
||||
"group_name": group.group_name,
|
||||
"ctime": timestamp_to_isoformat_timestr(group.timestamp),
|
||||
"creator_email": group.creator_name,
|
||||
"creator_name": email2nickname(group.creator_name),
|
||||
'creator_contact_email': email2contact_email(group.creator_name),
|
||||
}
|
||||
return Response(group_info)
|
||||
|
@@ -13,7 +13,8 @@ from .api.group_members import AdminGroupMembers, AdminGroupMember
|
||||
from .api.admin.users import OrgAdminUser, OrgAdminUsers, OrgAdminSearchUser, \
|
||||
OrgAdminImportUsers, OrgAdminInviteUser
|
||||
from .api.admin.user_set_password import OrgAdminUserSetPassword
|
||||
from .api.admin.groups import OrgAdminGroups, OrgAdminGroup, OrgAdminSearchGroup, OrgAdminDepartments
|
||||
from .api.admin.groups import OrgAdminGroups, OrgAdminGroup, OrgAdminSearchGroup, \
|
||||
OrgAdminDepartments, OrgAdminGroupToDeptView
|
||||
from .api.admin.repos import OrgAdminRepos, OrgAdminRepo
|
||||
from .api.admin.trash_libraries import OrgAdminTrashLibraries, OrgAdminTrashLibrary
|
||||
from .api.admin.info import OrgAdminInfo
|
||||
@@ -72,6 +73,7 @@ urlpatterns = [
|
||||
path('<int:org_id>/admin/search-group/', OrgAdminSearchGroup.as_view(), name='api-v2.1-org-admin-search-group'),
|
||||
path('<int:org_id>/admin/groups/<int:group_id>/', OrgAdminGroup.as_view(), name='api-admin-group'),
|
||||
path('<int:org_id>/admin/groups/<int:group_id>/libraries/', AdminGroupLibraries.as_view(), name='api-admin-group-libraries'),
|
||||
path('<int:org_id>/admin/groups/<int:group_id>/group-to-department/', OrgAdminGroupToDeptView.as_view(), name='api-admin-group-to-department'),
|
||||
re_path(r'^(?P<org_id>\d+)/admin/groups/(?P<group_id>\d+)/libraries/(?P<repo_id>[-0-9a-f]{36})/$', AdminGroupLibrary.as_view(), name='api-admin-group-library'),
|
||||
|
||||
path('<int:org_id>/admin/groups/<int:group_id>/group-owned-libraries/', AdminGroupOwnedLibraries.as_view(), name='api-admin-group-owned-libraries'),
|
||||
|
@@ -151,7 +151,8 @@ from seahub.api2.endpoints.admin.system_library import AdminSystemLibrary, \
|
||||
AdminSystemLibraryUploadLink
|
||||
from seahub.api2.endpoints.admin.default_library import AdminDefaultLibrary
|
||||
from seahub.api2.endpoints.admin.trash_libraries import AdminTrashLibraries, AdminTrashLibrary
|
||||
from seahub.api2.endpoints.admin.groups import AdminGroups, AdminGroup, AdminSearchGroup, AdminDepartments
|
||||
from seahub.api2.endpoints.admin.groups import AdminGroups, AdminGroup, AdminSearchGroup, \
|
||||
AdminDepartments, AdminGroupToDeptView
|
||||
from seahub.api2.endpoints.admin.group_libraries import AdminGroupLibraries, AdminGroupLibrary
|
||||
from seahub.api2.endpoints.admin.group_members import AdminGroupMembers, AdminGroupMember
|
||||
from seahub.api2.endpoints.admin.shares import AdminShares
|
||||
@@ -655,6 +656,7 @@ urlpatterns = [
|
||||
re_path(r'^api/v2.1/admin/groups/(?P<group_id>\d+)/members/(?P<email>[^/]+)/$', AdminGroupMember.as_view(), name='api-v2.1-admin-group-member'),
|
||||
re_path(r'^api/v2.1/admin/groups/(?P<group_id>\d+)/group-owned-libraries/$', AdminGroupOwnedLibraries.as_view(), name='api-v2.1-admin-group-owned-libraries'),
|
||||
re_path(r'^api/v2.1/admin/groups/(?P<group_id>\d+)/group-owned-libraries/(?P<repo_id>[-0-9a-f]{36})/$', AdminGroupOwnedLibrary.as_view(), name='api-v2.1-admin-owned-group-library'),
|
||||
re_path(r'^api/v2.1/admin/groups/(?P<group_id>\d+)/group-to-department/', AdminGroupToDeptView.as_view(), name='api-v2.1-admin-group-to-department'),
|
||||
|
||||
## admin::departments
|
||||
re_path(r'api/v2.1/admin/departments/$', AdminDepartments.as_view(), name='api-v2.1-admin-departments'),
|
||||
|
@@ -163,7 +163,6 @@ class CcnetDB:
|
||||
|
||||
return users, total_count
|
||||
|
||||
|
||||
def get_group_ids_admins_map(self, group_ids):
|
||||
group_admins = {}
|
||||
group_ids_str = ','.join(str(id) for id in group_ids)
|
||||
@@ -183,3 +182,21 @@ class CcnetDB:
|
||||
else:
|
||||
group_admins[group_id] = [user]
|
||||
return group_admins
|
||||
|
||||
def change_groups_into_departments(self, group_id):
|
||||
sql = f"""
|
||||
UPDATE `{self.db_name}`.`Group` g
|
||||
SET
|
||||
g.creator_name = 'system admin',
|
||||
g.parent_group_id = -1
|
||||
WHERE
|
||||
g.group_id = {group_id}
|
||||
"""
|
||||
structure_sql = f"""
|
||||
INSERT INTO `{self.db_name}`.`GroupStructure` (group_id, path)
|
||||
VALUES ('{group_id}', '{group_id}')
|
||||
"""
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(sql)
|
||||
cursor.execute(structure_sql)
|
||||
|
Reference in New Issue
Block a user