def get(self, request): if 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) data = { 'access_token': access_token, } department_id = request.GET.get('department_id', None) if department_id: data['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') error_msg = '获取企业微信组织架构失败' return api_error(status.HTTP_404_NOT_FOUND, error_msg) 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' ) error_msg = '获取企业微信组织架构失败' return api_error(status.HTTP_404_NOT_FOUND, error_msg) return Response(api_response_dic)
def work_weixin_oauth_connect_callback(request): if not work_weixin_oauth_check(): return render_error(request, _('Feature is not enabled.')) code = request.GET.get('code', None) state = request.GET.get('state', None) if state != request.session.get('work_weixin_oauth_connect_state', None) or not code: logger.error('can not get right code or state from work weixin request') return render_error(request, _('Error, please contact administrator.')) access_token = get_work_weixin_access_token() if not access_token: logger.error('can not get work weixin access_token') return render_error(request, _('Error, please contact administrator.')) data = { 'access_token': access_token, 'code': code, } api_response = requests.get(WORK_WEIXIN_GET_USER_INFO_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 user info') return render_error(request, _('Error, please contact administrator.')) if not api_response_dic.get('UserId', None): logger.error('can not get UserId in work weixin user info response') return render_error(request, _('Error, please contact administrator.')) user_id = api_response_dic.get('UserId') uid = WORK_WEIXIN_UID_PREFIX + user_id email = request.user.username work_weixin_user = SocialAuthUser.objects.get_by_provider_and_uid(WORK_WEIXIN_PROVIDER, uid) if work_weixin_user: logger.error('work weixin account already exists %s' % user_id) return render_error(request, '出错了,此企业微信账号已被绑定') SocialAuthUser.objects.add(email, WORK_WEIXIN_PROVIDER, uid) # update user info if WORK_WEIXIN_USER_INFO_AUTO_UPDATE: user_info_data = { 'access_token': access_token, 'userid': user_id, } user_info_api_response = requests.get(WORK_WEIXIN_GET_USER_PROFILE_URL, params=user_info_data) user_info_api_response_dic = handler_work_weixin_api_response(user_info_api_response) if user_info_api_response_dic: api_user = user_info_api_response_dic api_user['username'] = email api_user['contact_email'] = api_user['email'] update_work_weixin_user_info(api_user) # redirect user to page response = HttpResponseRedirect(request.session.get('work_weixin_oauth_connect_redirect', '/')) return response
def get(self, request, department_id): if not admin_work_weixin_departments_check(): error_msg = 'Feature is not enabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if not request.user.admin_permissions.can_manage_user(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') 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) data = { 'access_token': access_token, 'department_id': department_id, } fetch_child = request.GET.get('fetch_child', None) if fetch_child: if fetch_child not in ('true', 'false'): error_msg = 'fetch_child invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) data['fetch_child'] = 1 if fetch_child == 'true' else 0 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') error_msg = '获取企业微信组织架构成员失败' return api_error(status.HTTP_404_NOT_FOUND, error_msg) 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' ) error_msg = '获取企业微信组织架构成员失败' return api_error(status.HTTP_404_NOT_FOUND, error_msg) api_user_list = api_response_dic[WORK_WEIXIN_DEPARTMENT_MEMBERS_FIELD] # todo filter ccnet User database social_auth_queryset = SocialAuthUser.objects.filter( provider=WORK_WEIXIN_PROVIDER, uid__contains=WORK_WEIXIN_UID_PREFIX) for api_user in api_user_list: uid = WORK_WEIXIN_UID_PREFIX + api_user.get('userid', '') api_user['contact_email'] = api_user['email'] # # determine the user exists if social_auth_queryset.filter(uid=uid).exists(): api_user['email'] = social_auth_queryset.get(uid=uid).username else: api_user['email'] = '' return Response(api_response_dic)
def do_action(self): # work weixin check if not admin_work_weixin_departments_check(): self.log_error('Feature is not enabled.') return access_token = get_work_weixin_access_token() if not access_token: self.log_error('can not get work weixin access_token') return # list departments from work weixin api_department_list = self.list_departments_from_work_weixin( access_token) if api_department_list is None: self.log_error('获取企业微信组织架构失败') return api_department_list = sorted(api_department_list, key=lambda x: x['id']) self.log_debug('Total %d work-weixin departments.' % len(api_department_list)) # main count = 0 exists_count = 0 for department_obj in api_department_list: # check department argument group_name = department_obj.get('name') department_obj_id = department_obj.get('id') if department_obj_id is None or not group_name: continue # check department exist exist_department = ExternalDepartment.objects.get_by_provider_and_outer_id( WORK_WEIXIN_PROVIDER, department_obj_id) if exist_department: exists_count += 1 continue # sync to db group = self.get_group_by_name(group_name) if group: ExternalDepartment.objects.create( group_id=group.id, provider=WORK_WEIXIN_PROVIDER, outer_id=department_obj_id, ) count += 1 self.log_debug('%d work-weixin departments exists in db.' % exists_count) self.log_debug('Sync %d work-weixin departments to db.' % count)
def post(self, request): """import department from work weixin permission: IsProVersion """ if not request.user.admin_permissions.can_manage_user(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') # 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, })
def work_weixin_oauth_callback(request): if not work_weixin_oauth_check(): return render_error(request, _('Feature is not enabled.')) code = request.GET.get('code', None) state = request.GET.get('state', None) if state != request.session.get('work_weixin_oauth_state', None) or not code: logger.error( 'can not get right code or state from work weixin request') return render_error(request, _('Error, please contact administrator.')) access_token = get_work_weixin_access_token() if not access_token: logger.error('can not get work weixin access_token') return render_error(request, _('Error, please contact administrator.')) data = { 'access_token': access_token, 'code': code, } api_response = requests.get(WORK_WEIXIN_GET_USER_INFO_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 user info') return render_error(request, _('Error, please contact administrator.')) if not api_response_dic.get('UserId', None): logger.error('can not get UserId in work weixin user info response') return render_error(request, _('Error, please contact administrator.')) user_id = api_response_dic.get('UserId') uid = WORK_WEIXIN_UID_PREFIX + user_id work_weixin_user = SocialAuthUser.objects.get_by_provider_and_uid( WORK_WEIXIN_PROVIDER, uid) if work_weixin_user: email = work_weixin_user.username is_new_user = False else: email = gen_user_virtual_id() SocialAuthUser.objects.add(email, WORK_WEIXIN_PROVIDER, uid) is_new_user = True try: user = auth.authenticate(remote_user=email) except User.DoesNotExist: user = None if not user: return render_error( request, _('Error, new user registration is not allowed, please contact administrator.' )) # update user info if is_new_user or WORK_WEIXIN_USER_INFO_AUTO_UPDATE: user_info_data = { 'access_token': access_token, 'userid': user_id, } user_info_api_response = requests.get(WORK_WEIXIN_GET_USER_PROFILE_URL, params=user_info_data) user_info_api_response_dic = handler_work_weixin_api_response( user_info_api_response) if user_info_api_response_dic: api_user = user_info_api_response_dic api_user['username'] = email api_user['contact_email'] = api_user['email'] update_work_weixin_user_info(api_user) if not user.is_active: return render_error( request, _('Your account is created successfully, please wait for administrator to activate your account.' )) # User is valid. Set request.user and persist user in the session # by logging the user in. request.user = user auth.login(request, user) # generate auth token for Seafile client api_token = get_api_token(request) # redirect user to page response = HttpResponseRedirect( request.session.get('work_weixin_oauth_redirect', '/')) response.set_cookie('seahub_auth', user.username + '@' + api_token.key) return response
def do_action(self): # check before start if not work_weixin_notifications_check(): self.log_error('work weixin notifications settings check failed') return access_token = get_work_weixin_access_token() if not access_token: self.log_error('can not get access_token') return notice_url = WORK_WEIXIN_NOTIFICATIONS_URL + '?access_token=' + access_token detail_url = DTABLE_WEB_SERVICE_URL # start now = datetime.utcnow() today = datetime.utcnow().replace(hour=0).replace(minute=0). \ replace(second=0).replace(microsecond=0) # 1. get all users who are connected work weixin socials = SocialAuthUser.objects.filter( provider=WORK_WEIXIN_PROVIDER, uid__contains=WORK_WEIXIN_UID_PREFIX) users = [(x.username, x.uid[len(WORK_WEIXIN_UID_PREFIX):]) for x in socials] self.log_info('Found %d users' % len(users)) if not users: return user_uid_map = dict() for username, uid in users: user_uid_map[username] = uid # 2. get previous time that command last runs try: cmd_last_check = CommandsLastCheck.objects.get( command_type=self.label) self.log_debug('Last check time is %s' % cmd_last_check.last_check) last_check_dt = cmd_last_check.last_check cmd_last_check.last_check = now cmd_last_check.save() except CommandsLastCheck.DoesNotExist: last_check_dt = today self.log_debug('Create new last check time: %s' % now) CommandsLastCheck(command_type=self.label, last_check=now).save() # 3. get all unseen row comments for those users user_list = list(user_uid_map.keys()) with connection.cursor() as cursor: cursor.execute( "SELECT * FROM dtable_notifications WHERE created_at > %s" "AND seen = FALSE AND username IN %s", [last_check_dt, user_list]) rows = cursor.fetchall() if len(rows) == 0: return user_notices = {} for row in rows: if row[1] not in user_notices: user_notices[row[1]] = [row] else: user_notices[row[1]].append(row) cur_language = translation.get_language() translation.activate('zh-cn') # set language to zh-cn self.log_info('Set language to zh-cn') # 4. send msg to users site_name = get_site_name() for username, uid in users: notices = user_notices.get(username, []) count = len(notices) if count == 0: continue title = ungettext( "\n" "You've got 1 new notice on %(site_name)s:\n", "\n" "You've got %(num)s new notices on %(site_name)s:\n", count) % { 'num': count, 'site_name': site_name, } content = '\n'.join([format_notice(x) for x in notices]) self.send_work_weixin_msg(uid, title, content, detail_url, notice_url) translation.activate(cur_language) # reset language self.log_info('Reset language success')
def do_action(self): # check before start if not work_weixin_notifications_check(): self.log_error('work weixin notifications settings check failed') return access_token = get_work_weixin_access_token() if not access_token: self.log_error('can not get access_token') self.work_weixin_notifications_url = WORK_WEIXIN_NOTIFICATIONS_URL + '?access_token=' + access_token self.detail_url = get_site_scheme_and_netloc().rstrip('/') + reverse( 'user_notification_list') site_name = get_site_name() # start now = datetime.now() today = datetime.now().replace(hour=0).replace(minute=0).replace( second=0).replace(microsecond=0) # 1. get all users who are connected work weixin socials = SocialAuthUser.objects.filter( provider=WORK_WEIXIN_PROVIDER, uid__contains=WORK_WEIXIN_UID_PREFIX) users = [(x.username, x.uid[len(WORK_WEIXIN_UID_PREFIX):]) for x in socials] self.log_info('Found %d users' % len(users)) if not users: return user_uid_map = {} for username, uid in users: user_uid_map[username] = uid # 2. get previous time that command last runs try: cmd_last_check = CommandsLastCheck.objects.get( command_type=self.label) self.log_debug('Last check time is %s' % cmd_last_check.last_check) last_check_dt = cmd_last_check.last_check cmd_last_check.last_check = now cmd_last_check.save() except CommandsLastCheck.DoesNotExist: last_check_dt = today self.log_debug('Create new last check time: %s' % now) CommandsLastCheck(command_type=self.label, last_check=now).save() # 3. get all unseen notices for those users qs = UserNotification.objects.filter( timestamp__gt=last_check_dt).filter(seen=False).filter( to_user__in=list(user_uid_map.keys())) self.log_info('Found %d notices' % qs.count()) if qs.count() == 0: return user_notices = {} for q in qs: if q.to_user not in user_notices: user_notices[q.to_user] = [q] else: user_notices[q.to_user].append(q) # save current language cur_language = translation.get_language() # active zh-cn translation.activate('zh-cn') self.log_info('the language is set to zh-cn') # 4. send msg to users for username, uid in users: notices = user_notices.get(username, []) count = len(notices) if count == 0: continue title = ungettext( "\n" "You've got 1 new notice on %(site_name)s:\n", "\n" "You've got %(num)s new notices on %(site_name)s:\n", count) % { 'num': count, 'site_name': site_name, } content = ''.join([wrap_div(x.format_msg()) for x in notices]) self.send_work_weixin_msg(uid, title, content) # reset language translation.activate(cur_language) self.log_info('reset language success')
def do_action(self): if not ENABLE_DINGTALK and not ENABLE_WORK_WEIXIN: self.log_info('No social account enabled') return dingtalk_access_token = '' work_weixin_access_token = '' if ENABLE_DINGTALK: dingtalk_access_token = dingtalk_get_access_token() if not dingtalk_access_token: self.log_error('can not get access token for dingtalk') else: self.dingtalk_message_send_to_conversation_url = DINGTALK_MESSAGE_SEND_TO_CONVERSATION_URL + \ '?access_token=' + dingtalk_access_token self.detail_url = get_site_scheme_and_netloc().rstrip( '/') + reverse('user_notification_list') if ENABLE_WORK_WEIXIN: work_weixin_access_token = get_work_weixin_access_token() if not work_weixin_access_token: self.log_error('can not get access token for work weixin') else: self.work_weixin_notifications_url = WORK_WEIXIN_NOTIFICATIONS_URL + \ '?access_token=' + work_weixin_access_token self.detail_url = get_site_scheme_and_netloc().rstrip( '/') + reverse('user_notification_list') if not dingtalk_access_token and not work_weixin_access_token: return # save current language cur_language = translation.get_language() # active zh-cn translation.activate('zh-cn') self.log_info('the language is set to zh-cn') # 1. get previous time that command last runs now = datetime.now() today = datetime.now().replace(hour=0).replace(minute=0).replace( second=0).replace(microsecond=0) try: cmd_last_check = CommandsLastCheck.objects.get( command_type=self.label) self.log_debug('Last check time is %s' % cmd_last_check.last_check) last_check_dt = cmd_last_check.last_check cmd_last_check.last_check = now cmd_last_check.save() except CommandsLastCheck.DoesNotExist: last_check_dt = today self.log_debug('Create new last check time: %s' % now) CommandsLastCheck(command_type=self.label, last_check=now).save() # 2. get all unseen notices user_notifications = UserNotification.objects.filter( timestamp__gt=last_check_dt).filter(seen=False) self.log_info('Found %d notices' % user_notifications.count()) if user_notifications.count() == 0: return # 3. get all users should send notice to user_email_list = list( set([item.to_user for item in user_notifications])) dingtail_socials = SocialAuthUser.objects.filter( provider='dingtalk').filter(username__in=user_email_list) dingtalk_email_list = [item.username for item in dingtail_socials] dingtalk_email_uid_dict = {} for item in dingtail_socials: dingtalk_email_uid_dict[ item.username] = dingtalk_get_userid_by_unionid(item.uid) work_weixin_socials = SocialAuthUser.objects.filter(provider=WORK_WEIXIN_PROVIDER, \ uid__contains=WORK_WEIXIN_UID_PREFIX).filter(username__in=user_email_list) work_weixin_email_list = [ item.username for item in work_weixin_socials ] work_weixin_email_uid_dict = {} for item in work_weixin_socials: work_weixin_email_uid_dict[ item.username] = item.uid[len(WORK_WEIXIN_UID_PREFIX):] # 4. send msg site_name = get_site_name() for email in list(set(dingtalk_email_list + work_weixin_email_list)): should_send = [] for notification in user_notifications: if email == notification.to_user: should_send.append(notification) title = _("You've got %(num)s new notices on %(site_name)s:\n") % \ {'num': len(should_send), 'site_name': site_name, } has_sent = False if not has_sent and email in dingtalk_email_list and ENABLE_DINGTALK: content = ' \n '.join([ remove_html_a_element_for_dingtalk(x.format_msg()) for x in should_send ]) self.send_dingtalk_msg(dingtalk_email_uid_dict[email], title, content) has_sent = True if not has_sent and email in work_weixin_email_list and ENABLE_WORK_WEIXIN: content = ''.join([ wrap_div_for_work_weixin(x.format_msg()) for x in should_send ]) self.send_work_weixin_msg(work_weixin_email_uid_dict[email], title, content) has_sent = True translation.activate(cur_language) self.log_info('reset language success') return