Пример #1
0
    def get(self, request):

        if not ENABLE_DINGTALK:
            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 = dingtalk_get_access_token()
        if not 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', '')
        if department_id:
            data['id'] = department_id
            current_department_resp_json = requests.get(DINGTALK_DEPARTMENT_GET_DEPARTMENT_URL, params=data).json()
            current_department_list = [current_department_resp_json]
            sub_department_resp_json = requests.get(DINGTALK_DEPARTMENT_LIST_DEPARTMENT_URL, params=data).json()
            sub_department_list = sub_department_resp_json.get('department', [])
            department_list = current_department_list + sub_department_list
            return Response({'department': department_list})
        else:
            resp_json = requests.get(DINGTALK_DEPARTMENT_LIST_DEPARTMENT_URL, params=data).json()
            return Response(resp_json)
Пример #2
0
    def do_action(self):
       # dingtalk check
        if not ENABLE_DINGTALK:
            self.log_error('Feature is not enabled.')
            return

        access_token = dingtalk_get_access_token()
        if not access_token:
            self.log_error('can not get dingtalk access_token')
            return

        # get department list
        # https://developers.dingtalk.com/document/app/obtain-the-department-list-v2
        api_department_list = self.list_departments_from_dingtalk(
            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 dingtalk 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(
                DINGTALK_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=DINGTALK_PROVIDER,
                    outer_id=department_obj_id,
                )
                count += 1

        self.log_debug('%d dingtalk departments exists in db.' % exists_count)
        self.log_debug('Sync %d dingtalk departments to db.' % count)
Пример #3
0
    def get(self, request, department_id):

        if not ENABLE_DINGTALK:
            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 = dingtalk_get_access_token()
        if not access_token:
            error_msg = '获取钉钉组织架构成员失败'
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        data = {
            'access_token': access_token,
            'department_id': department_id,
            'offset': 0,
            'size': DINGTALK_DEPARTMENT_USER_SIZE,
        }
        resp_json = requests.get(
            DINGTALK_DEPARTMENT_GET_DEPARTMENT_USER_LIST_URL,
            params=data).json()

        user_id_name_dict = {}
        auth_users = SocialAuthUser.objects.filter(provider='dingtalk')
        for user in auth_users:
            user_id_name_dict[user.uid] = user.username

        for user in resp_json['userlist']:
            uid = user.get('unionid', '')
            user['contact_email'] = user.get('email', '')
            user['userid'] = uid

            # #  determine the user exists
            if uid in user_id_name_dict.keys():
                user['email'] = user_id_name_dict[uid]
            else:
                user['email'] = ''

        return Response(resp_json)
Пример #4
0
    def post(self, request):
        """import department from dingtalk
        """

        if not ENABLE_DINGTALK:
            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.')

        # argument check
        department_id = request.data.get('department_id')
        try:
            department_id = int(department_id)
        except Exception as e:
            logger.error(e)
            error_msg = 'department_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        access_token = dingtalk_get_access_token()
        if not access_token:
            error_msg = '获取钉钉组织架构失败'
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # get department list
        # https://developers.dingtalk.com/document/app/obtain-the-department-list
        data = {'access_token': access_token, 'id': department_id}
        current_department_resp_json = requests.get(DINGTALK_DEPARTMENT_GET_DEPARTMENT_URL, params=data).json()
        current_department_list = [current_department_resp_json]
        sub_department_resp_json = requests.get(DINGTALK_DEPARTMENT_LIST_DEPARTMENT_URL, params=data).json()
        sub_department_list = sub_department_resp_json.get('department', [])
        department_list = current_department_list + sub_department_list
        department_list = sorted(department_list, key=lambda x:x['id'])

        # get department user list
        data = {
            'access_token': access_token,
            'department_id': department_id,
            'offset': 0,
            'size': DINGTALK_DEPARTMENT_USER_SIZE,
        }
        user_resp_json = requests.get(DINGTALK_DEPARTMENT_GET_DEPARTMENT_USER_LIST_URL, params=data).json()
        api_user_list = user_resp_json.get('userlist', [])

        # main
        success = list()
        failed = list()
        department_map_to_group_dict = dict()

        for index, department_obj in enumerate(department_list):
            # check department argument
            new_group_name = department_obj.get('name')
            department_obj_id = department_obj.get('id')
            parent_department_id = department_obj.get('parentid', 0)
            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_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
            exist_department = ExternalDepartment.objects.get_by_provider_and_outer_id(
                DINGTALK_PROVIDER, department_obj_id)
            if exist_department:
                department_map_to_group_dict[department_obj_id] = exist_department.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)

                ExternalDepartment.objects.create(
                    group_id=group_id,
                    provider=DINGTALK_PROVIDER,
                    outer_id=department_obj_id,
                )

                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='dingtalk')

        # import api_user
        for api_user in api_user_list:
            uid = api_user.get('unionid', '')
            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()
                try:
                    User.objects.create_user(email)
                    SocialAuthUser.objects.add(email, 'dingtalk', uid)
                except Exception as e:
                    logger.error(e)
                    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, in_structure=False):
                    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)

                try:
                    update_dingtalk_user_info(email,
                                              api_user.get('name'),
                                              api_user.get('contact_email'),
                                              api_user.get('avatar'))
                except Exception as e:
                    logger.error(e)

        return Response({
            'success': success,
            'failed': failed,
        })
    def do_action(self):

        # check before start
        access_token = dingtalk_get_access_token()
        if not access_token:
            self.log_error('can not get access_token')

        self.dingtalk_message_send_to_conversation_url = DINGTALK_MESSAGE_SEND_TO_CONVERSATION_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 dingtalk
        socials = SocialAuthUser.objects.filter(provider='dingtalk')
        users = [(x.username, x.uid) 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] = dingtalk_get_userid_by_unionid(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:
            user_id = user_uid_map[username]
            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(
                [remove_html_a_element(x.format_msg()) for x in notices])
            self.send_dingtalk_msg(user_id, 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