diff --git a/seahub/api2/endpoints/admin/dingtalk.py b/seahub/api2/endpoints/admin/dingtalk.py index 426b95f76f..400af0a541 100644 --- a/seahub/api2/endpoints/admin/dingtalk.py +++ b/seahub/api2/endpoints/admin/dingtalk.py @@ -5,7 +5,6 @@ import logging import requests -from django.core.cache import cache from django.core.files.base import ContentFile from rest_framework.authentication import SessionAuthentication @@ -28,9 +27,8 @@ from seahub.profile.models import Profile from seahub.avatar.models import Avatar from seahub.group.utils import validate_group_name -from seahub.utils import normalize_cache_key -from seahub.dingtalk.settings import ENABLE_DINGTALK, DINGTALK_DEPARTMENT_APP_KEY, \ - DINGTALK_DEPARTMENT_APP_SECRET, DINGTALK_DEPARTMENT_GET_ACCESS_TOKEN_URL, \ +from seahub.dingtalk.utils import dingtalk_get_access_token +from seahub.dingtalk.settings import ENABLE_DINGTALK, \ DINGTALK_DEPARTMENT_LIST_DEPARTMENT_URL, \ DINGTALK_DEPARTMENT_GET_DEPARTMENT_URL, \ DINGTALK_DEPARTMENT_GET_DEPARTMENT_USER_LIST_URL, \ @@ -40,34 +38,6 @@ DEPARTMENT_OWNER = 'system admin' logger = logging.getLogger(__name__) - -def get_dingtalk_access_token(): - - cache_key = normalize_cache_key('DINGTALK_ACCESS_TOKEN') - access_token = cache.get(cache_key, None) - - if not access_token: - - data = { - 'appkey': DINGTALK_DEPARTMENT_APP_KEY, - 'appsecret': DINGTALK_DEPARTMENT_APP_SECRET, - } - resp_json = requests.get(DINGTALK_DEPARTMENT_GET_ACCESS_TOKEN_URL, - params=data).json() - - access_token = resp_json.get('access_token', '') - if not access_token: - logger.error('failed to get dingtalk access_token') - logger.error(data) - logger.error(DINGTALK_DEPARTMENT_GET_ACCESS_TOKEN_URL) - logger.error(resp_json) - return '' - - expires_in = resp_json.get('expires_in', 7200) - cache.set(cache_key, access_token, expires_in) - - return access_token - def update_dingtalk_user_info(email, name, contact_email, avatar_url): # make sure the contact_email is unique @@ -114,7 +84,7 @@ class AdminDingtalkDepartments(APIView): if not request.user.admin_permissions.can_manage_user(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') - access_token = get_dingtalk_access_token() + access_token = dingtalk_get_access_token() if not access_token: error_msg = '获取钉钉组织架构失败' return api_error(status.HTTP_404_NOT_FOUND, error_msg) @@ -151,7 +121,7 @@ class AdminDingtalkDepartmentMembers(APIView): if not request.user.admin_permissions.can_manage_user(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') - access_token = get_dingtalk_access_token() + access_token = dingtalk_get_access_token() if not access_token: error_msg = '获取钉钉组织架构成员失败' return api_error(status.HTTP_404_NOT_FOUND, error_msg) @@ -320,7 +290,7 @@ class AdminDingtalkDepartmentsImport(APIView): error_msg = 'department_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) - access_token = get_dingtalk_access_token() + access_token = dingtalk_get_access_token() if not access_token: error_msg = '获取钉钉组织架构失败' return api_error(status.HTTP_404_NOT_FOUND, error_msg) diff --git a/seahub/dingtalk/settings.py b/seahub/dingtalk/settings.py index ca3756702b..3d806defce 100644 --- a/seahub/dingtalk/settings.py +++ b/seahub/dingtalk/settings.py @@ -1,6 +1,8 @@ import seahub.settings as settings ENABLE_DINGTALK = getattr(settings, 'ENABLE_DINGTALK', False) +DINGTALK_AGENT_ID = getattr(settings, 'DINGTALK_AGENT_ID', '') +DINGTALK_GET_USERID_BY_UNIONID = getattr(settings, 'DINGTALK_GET_USERID_BY_UNIONID', 'https://oapi.dingtalk.com/user/getUseridByUnionid') # for dingtalk qr connect DINGTALK_QR_CONNECT_LOGIN_REMEMBER_ME = True @@ -21,3 +23,6 @@ DINGTALK_DEPARTMENT_LIST_DEPARTMENT_URL = getattr(settings, 'DINGTALK_DEPARTMENT DINGTALK_DEPARTMENT_GET_DEPARTMENT_URL = getattr(settings, 'DINGTALK_DEPARTMENT_GET_DEPARTMENT_URL', 'https://oapi.dingtalk.com/department/get') DINGTALK_DEPARTMENT_GET_DEPARTMENT_USER_LIST_URL = getattr(settings, 'DINGTALK_DEPARTMENT_GET_DEPARTMENT_USER_LIST_URL', 'https://oapi.dingtalk.com/user/listbypage') DINGTALK_DEPARTMENT_USER_SIZE = 100 + +# for dingtalk message +DINGTALK_MESSAGE_SEND_TO_CONVERSATION_URL = getattr(settings, 'DINGTALK_MESSAGE_SEND_TO_CONVERSATION_URL', 'https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2') diff --git a/seahub/dingtalk/utils.py b/seahub/dingtalk/utils.py new file mode 100644 index 0000000000..d803f8cb3f --- /dev/null +++ b/seahub/dingtalk/utils.py @@ -0,0 +1,63 @@ +import logging +import requests + +from django.core.cache import cache +from seahub.utils import normalize_cache_key + +from seahub.dingtalk.settings import DINGTALK_DEPARTMENT_APP_KEY, \ + DINGTALK_DEPARTMENT_APP_SECRET, \ + DINGTALK_DEPARTMENT_GET_ACCESS_TOKEN_URL, \ + DINGTALK_GET_USERID_BY_UNIONID + +logger = logging.getLogger(__name__) + +def dingtalk_get_access_token(): + + cache_key = normalize_cache_key('DINGTALK_ACCESS_TOKEN') + access_token = cache.get(cache_key, None) + if access_token: + return access_token + + data = { + 'appkey': DINGTALK_DEPARTMENT_APP_KEY, + 'appsecret': DINGTALK_DEPARTMENT_APP_SECRET, + } + resp_json = requests.get(DINGTALK_DEPARTMENT_GET_ACCESS_TOKEN_URL, + params=data).json() + + access_token = resp_json.get('access_token', '') + if not access_token: + logger.error('failed to get dingtalk access_token') + logger.error(DINGTALK_DEPARTMENT_GET_ACCESS_TOKEN_URL) + logger.error(data) + logger.error(resp_json) + return '' + + expires_in = resp_json.get('expires_in', 7200) + cache.set(cache_key, access_token, expires_in) + + return access_token + +def dingtalk_get_userid_by_unionid(union_id): + + cache_key = normalize_cache_key('DINGTALK_UNION_ID_%s' % union_id) + user_id = cache.get(cache_key, None) + if user_id: + return user_id + + access_token = dingtalk_get_access_token() + data = { + 'access_token': access_token, + 'unionid': union_id, + } + resp_json = requests.get(DINGTALK_GET_USERID_BY_UNIONID, params=data).json() + user_id = resp_json.get('userid', '') + if not user_id: + logger.error('failed to get userid by unionid: %s' % union_id) + logger.error(DINGTALK_GET_USERID_BY_UNIONID) + logger.error(data) + logger.error(resp_json) + return '' + + cache.set(cache_key, user_id) + return user_id diff --git a/seahub/notifications/management/commands/send_dingtalk_notifications.py b/seahub/notifications/management/commands/send_dingtalk_notifications.py new file mode 100644 index 0000000000..ae8157c717 --- /dev/null +++ b/seahub/notifications/management/commands/send_dingtalk_notifications.py @@ -0,0 +1,179 @@ +# Copyright (c) 2012-2019 Seafile Ltd. +# encoding: utf-8 +from datetime import datetime +import logging +import re +import requests +import json + +from django.core.management.base import BaseCommand +from django.core.urlresolvers import reverse +from django.utils import translation +from django.utils.translation import ungettext + +from seahub.base.models import CommandsLastCheck +from seahub.notifications.models import UserNotification +from seahub.utils import get_site_scheme_and_netloc, get_site_name +from seahub.auth.models import SocialAuthUser + +from seahub.dingtalk.utils import dingtalk_get_access_token, dingtalk_get_userid_by_unionid +from seahub.dingtalk.settings import DINGTALK_MESSAGE_SEND_TO_CONVERSATION_URL, \ + DINGTALK_AGENT_ID + +# Get an instance of a logger +logger = logging.getLogger(__name__) + + +# https://ding-doc.dingtalk.com/doc#/serverapi3/wvdxel + +########## Utility Functions ########## +def remove_html_a_element(s): + """ + Replace xx to xx and wrap content with
. + """ + patt = '