this.props.onChangeDepartment(department.id)}>
+
this.props.onChangeDepartment(department.id)}
+ onMouseEnter={this.onMouseEnter}
+ onMouseLeave={this.onMouseLeave}
+ >
this.toggleChildren(e)}>{' '}
{department.name}
+ {isPro &&
+
+
+
+
+ {'导入部门'}
+
+
+ }
}
{this.state.isChildrenShow &&
diff --git a/frontend/src/pages/sys-admin/work-weixin/work-weixin-departments-tree-panel.js b/frontend/src/pages/sys-admin/work-weixin/work-weixin-departments-tree-panel.js
index 080d6e39a5..fb41302648 100644
--- a/frontend/src/pages/sys-admin/work-weixin/work-weixin-departments-tree-panel.js
+++ b/frontend/src/pages/sys-admin/work-weixin/work-weixin-departments-tree-panel.js
@@ -8,6 +8,7 @@ const WorkWeixinDepartmentsTreePanelPropTypes = {
departmentsTree: PropTypes.array.isRequired,
onChangeDepartment: PropTypes.func.isRequired,
checkedDepartmentId: PropTypes.number.isRequired,
+ importDepartmentDialogToggle: PropTypes.func.isRequired,
};
class WorkWeixinDepartmentsTreePanel extends Component {
@@ -33,6 +34,7 @@ class WorkWeixinDepartmentsTreePanel extends Component {
isChildrenShow={true}
onChangeDepartment={this.props.onChangeDepartment}
checkedDepartmentId={this.props.checkedDepartmentId}
+ importDepartmentDialogToggle={this.props.importDepartmentDialogToggle}
/>
);
})}
diff --git a/seahub/api2/endpoints/admin/work_weixin.py b/seahub/api2/endpoints/admin/work_weixin.py
index b248a97f27..ae318045a4 100644
--- a/seahub/api2/endpoints/admin/work_weixin.py
+++ b/seahub/api2/endpoints/admin/work_weixin.py
@@ -5,6 +5,7 @@ import logging
import requests
import json
+from seaserv import seafile_api, ccnet_api
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response
@@ -13,6 +14,8 @@ from rest_framework import status
from seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle
from seahub.api2.utils import api_error
+from seahub.api2.permissions import IsProVersion
+
from seahub.work_weixin.utils import handler_work_weixin_api_response, \
get_work_weixin_access_token, admin_work_weixin_departments_check, \
update_work_weixin_user_info
@@ -21,10 +24,13 @@ from seahub.work_weixin.settings import WORK_WEIXIN_DEPARTMENTS_URL, \
from seahub.base.accounts import User
from seahub.utils.auth import gen_user_virtual_id
from seahub.auth.models import SocialAuthUser
+from seahub.group.utils import validate_group_name
logger = logging.getLogger(__name__)
WORK_WEIXIN_DEPARTMENT_FIELD = 'department'
WORK_WEIXIN_DEPARTMENT_MEMBERS_FIELD = 'userlist'
+DEPARTMENT_OWNER = 'system admin'
+
# # uid = corpid + '_' + userid
# from social_django.models import UserSocialAuth
@@ -149,7 +155,6 @@ def _handler_work_weixin_user_data(api_user, social_auth_queryset):
def _import_user_from_work_weixin(email, api_user):
-
api_user['username'] = email
uid = WORK_WEIXIN_UID_PREFIX + api_user.get('userid')
try:
@@ -204,3 +209,235 @@ class AdminWorkWeixinUsersBatch(APIView):
failed.append(error_data)
return Response({'success': success, 'failed': failed})
+
+
+class AdminWorkWeixinDepartmentsImport(APIView):
+ authentication_classes = (TokenAuthentication, SessionAuthentication)
+ throttle_classes = (UserRateThrottle,)
+ permission_classes = (IsAdminUser,)
+
+ def _list_departments_from_work_weixin(self, access_token, department_id):
+ data = {
+ 'access_token': access_token,
+ 'id': department_id,
+ }
+ api_response = requests.get(WORK_WEIXIN_DEPARTMENTS_URL, params=data)
+ api_response_dic = handler_work_weixin_api_response(api_response)
+
+ if not api_response_dic:
+ logger.error('can not get work weixin departments response')
+ return None
+
+ if WORK_WEIXIN_DEPARTMENT_FIELD not in api_response_dic:
+ logger.error(json.dumps(api_response_dic))
+ logger.error('can not get department list in work weixin departments response')
+ return None
+
+ return api_response_dic[WORK_WEIXIN_DEPARTMENT_FIELD]
+
+ def _list_department_members_from_work_weixin(self, access_token, department_id):
+ data = {
+ 'access_token': access_token,
+ 'department_id': department_id,
+ 'fetch_child': 1,
+ }
+ api_response = requests.get(WORK_WEIXIN_DEPARTMENT_MEMBERS_URL, params=data)
+ api_response_dic = handler_work_weixin_api_response(api_response)
+
+ if not api_response_dic:
+ logger.error('can not get work weixin department members response')
+ return None
+
+ if WORK_WEIXIN_DEPARTMENT_MEMBERS_FIELD not in api_response_dic:
+ logger.error(json.dumps(api_response_dic))
+ logger.error('can not get userlist in work weixin department members response')
+ return None
+
+ return api_response_dic[WORK_WEIXIN_DEPARTMENT_MEMBERS_FIELD]
+
+ def _admin_check_group_name_conflict(self, new_group_name):
+ checked_groups = ccnet_api.search_groups(new_group_name, -1, -1)
+
+ for g in checked_groups:
+ if g.group_name == new_group_name:
+ return True, g
+
+ return False, None
+
+ def _api_department_success_msg(self, department_obj_id, department_obj_name, group_id):
+ return {
+ 'type': 'department',
+ 'department_id': department_obj_id,
+ 'department_name': department_obj_name,
+ 'group_id': group_id,
+ }
+
+ def _api_department_failed_msg(self, department_obj_id, department_obj_name, msg):
+ return {
+ 'type': 'department',
+ 'department_id': department_obj_id,
+ 'department_name': department_obj_name,
+ 'msg': msg,
+ }
+
+ def _api_user_success_msg(self, email, api_user_name, department_obj_id, group_id):
+ return {
+ 'type': 'user',
+ 'email': email,
+ 'api_user_name': api_user_name,
+ 'department_id': department_obj_id,
+ 'group_id': group_id,
+ }
+
+ def _api_user_failed_msg(self, email, api_user_name, department_obj_id, msg):
+ return {
+ 'type': 'user',
+ 'email': email,
+ 'api_user_name': api_user_name,
+ 'department_id': department_obj_id,
+ 'msg': msg,
+ }
+
+ def post(self, request):
+ """import department from work weixin
+
+ permission: IsProVersion
+ """
+ # argument check
+ department_id = request.data.get('work_weixin_department_id')
+ try:
+ department_id = int(department_id)
+ except Exception as e:
+ logger.error(e)
+ error_msg = 'work_weixin_department_ids invalid.'
+ return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
+
+ # is pro version and work weixin check
+ if not IsProVersion or not admin_work_weixin_departments_check():
+ error_msg = 'Feature is not enabled.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ access_token = get_work_weixin_access_token()
+ if not access_token:
+ logger.error('can not get work weixin access_token')
+ error_msg = '获取企业微信组织架构失败'
+ return api_error(status.HTTP_404_NOT_FOUND, error_msg)
+
+ # list departments from work weixin
+ api_department_list = self._list_departments_from_work_weixin(access_token, department_id)
+ if api_department_list is None:
+ error_msg = '获取企业微信组织架构失败'
+ return api_error(status.HTTP_404_NOT_FOUND, error_msg)
+
+ # list department members from work weixin
+ api_user_list = self._list_department_members_from_work_weixin(access_token, department_id)
+ if api_user_list is None:
+ error_msg = '获取企业微信组织架构成员失败'
+ return api_error(status.HTTP_404_NOT_FOUND, error_msg)
+
+ # main
+ success = list()
+ failed = list()
+ department_map_to_group_dict = dict()
+
+ for index, department_obj in enumerate(api_department_list):
+ # check department argument
+ new_group_name = department_obj.get('name')
+ department_obj_id = department_obj.get('id')
+ if department_obj_id is None or not new_group_name or not validate_group_name(new_group_name):
+ failed_msg = self._api_department_failed_msg(
+ department_obj_id, new_group_name, '部门参数错误')
+ failed.append(failed_msg)
+ continue
+
+ # check parent group
+ if index == 0:
+ parent_group_id = -1
+ else:
+ parent_department_id = department_obj.get('parentid')
+ parent_group_id = department_map_to_group_dict.get(parent_department_id)
+
+ if parent_group_id is None:
+ failed_msg = self._api_department_failed_msg(
+ department_obj_id, new_group_name, '父级部门不存在')
+ failed.append(failed_msg)
+ continue
+
+ # check department exist by group name
+ exist, exist_group = self._admin_check_group_name_conflict(new_group_name)
+ if exist:
+ department_map_to_group_dict[department_obj_id] = exist_group.id
+ failed_msg = self._api_department_failed_msg(
+ department_obj_id, new_group_name, '部门已存在')
+ failed.append(failed_msg)
+ continue
+
+ # import department
+ try:
+ group_id = ccnet_api.create_group(
+ new_group_name, DEPARTMENT_OWNER, parent_group_id=parent_group_id)
+
+ seafile_api.set_group_quota(group_id, -2)
+
+ department_map_to_group_dict[department_obj_id] = group_id
+ success_msg = self._api_department_success_msg(
+ department_obj_id, new_group_name, group_id)
+ success.append(success_msg)
+ except Exception as e:
+ logger.error(e)
+ failed_msg = self._api_department_failed_msg(
+ department_obj_id, new_group_name, '部门导入失败')
+ failed.append(failed_msg)
+
+ # todo filter ccnet User database
+ social_auth_queryset = SocialAuthUser.objects.filter(
+ provider=WORK_WEIXIN_PROVIDER, uid__contains=WORK_WEIXIN_UID_PREFIX)
+
+ # import api_user
+ for api_user in api_user_list:
+ uid = WORK_WEIXIN_UID_PREFIX + api_user.get('userid', '')
+ api_user['contact_email'] = api_user['email']
+ api_user_name = api_user.get('name')
+
+ # determine the user exists
+ if social_auth_queryset.filter(uid=uid).exists():
+ email = social_auth_queryset.get(uid=uid).username
+ else:
+ # create user
+ email = gen_user_virtual_id()
+ create_user_success = _import_user_from_work_weixin(email, api_user)
+ if not create_user_success:
+ failed_msg = self._api_user_failed_msg(
+ '', api_user_name, department_id, '导入用户失败')
+ failed.append(failed_msg)
+ continue
+
+ # bind user to department
+ api_user_department_list = api_user.get('department')
+ for department_obj_id in api_user_department_list:
+ group_id = department_map_to_group_dict.get(department_obj_id)
+ if group_id is None:
+ # the api_user also exist in the brother department which not import
+ continue
+
+ if ccnet_api.is_group_user(group_id, email):
+ failed_msg = self._api_user_failed_msg(
+ email, api_user_name, department_obj_id, '部门成员已存在')
+ failed.append(failed_msg)
+ continue
+
+ try:
+ ccnet_api.group_add_member(group_id, DEPARTMENT_OWNER, email)
+ success_msg = self._api_user_success_msg(
+ email, api_user_name, department_obj_id, group_id)
+ success.append(success_msg)
+ except Exception as e:
+ logger.error(e)
+ failed_msg = self._api_user_failed_msg(
+ email, api_user_name, department_id, '导入部门成员失败')
+ failed.append(failed_msg)
+
+ return Response({
+ 'success': success,
+ 'failed': failed,
+ })
diff --git a/seahub/urls.py b/seahub/urls.py
index a212d7113b..27ff07831f 100644
--- a/seahub/urls.py
+++ b/seahub/urls.py
@@ -145,7 +145,7 @@ from seahub.api2.endpoints.admin.user_activities import UserActivitiesView
from seahub.api2.endpoints.admin.file_scan_records import AdminFileScanRecords
from seahub.api2.endpoints.admin.notifications import AdminNotificationsView
from seahub.api2.endpoints.admin.work_weixin import AdminWorkWeixinDepartments, \
- AdminWorkWeixinDepartmentMembers, AdminWorkWeixinUsersBatch
+ AdminWorkWeixinDepartmentMembers, AdminWorkWeixinUsersBatch, AdminWorkWeixinDepartmentsImport
from seahub.api2.endpoints.file_participants import FileParticipantsView, FileParticipantView
urlpatterns = [
@@ -567,6 +567,7 @@ urlpatterns = [
url(r'^api/v2.1/admin/work-weixin/departments/$', AdminWorkWeixinDepartments.as_view(), name='api-v2.1-admin-work-weixin-departments'),
url(r'^api/v2.1/admin/work-weixin/departments/(?P
\d+)/members/$', AdminWorkWeixinDepartmentMembers.as_view(), name='api-v2.1-admin-work-weixin-department-members'),
url(r'^api/v2.1/admin/work-weixin/users/batch/$', AdminWorkWeixinUsersBatch.as_view(), name='api-v2.1-admin-work-weixin-users'),
+ url(r'^api/v2.1/admin/work-weixin/departments/import/$', AdminWorkWeixinDepartmentsImport.as_view(), name='api-v2.1-admin-work-weixin-department-import'),
### system admin ###
url(r'^sysadmin/$', sysadmin, name='sysadmin'),