mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-31 14:42:10 +00:00
dingtalk new (#5393)
This commit is contained in:
@@ -28,13 +28,24 @@ from seahub.avatar.models import Avatar
|
||||
from seahub.group.utils import validate_group_name
|
||||
from seahub.auth.models import ExternalDepartment
|
||||
|
||||
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, \
|
||||
DINGTALK_DEPARTMENT_USER_SIZE, DINGTALK_PROVIDER
|
||||
|
||||
|
||||
# for 10.0 or later
|
||||
from seahub.dingtalk.settings import DINGTALK_APP_KEY, \
|
||||
DINGTALK_APP_SECRET
|
||||
|
||||
if DINGTALK_APP_KEY and DINGTALK_APP_SECRET:
|
||||
from seahub.dingtalk.utils import \
|
||||
dingtalk_get_orgapp_token as dingtalk_get_access_token
|
||||
else:
|
||||
from seahub.dingtalk.utils import dingtalk_get_access_token
|
||||
|
||||
|
||||
DEPARTMENT_OWNER = 'system admin'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -300,7 +311,7 @@ class AdminDingtalkDepartmentsImport(APIView):
|
||||
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'])
|
||||
department_list = sorted(department_list, key=lambda x: x['id'])
|
||||
|
||||
# get department user list
|
||||
data = {
|
||||
|
@@ -1,7 +1,44 @@
|
||||
import seahub.settings as settings
|
||||
|
||||
# constants
|
||||
DINGTALK_PROVIDER = 'dingtalk'
|
||||
|
||||
ENABLE_DINGTALK = getattr(settings, 'ENABLE_DINGTALK', False)
|
||||
DINGTALK_AGENT_ID = getattr(settings, 'DINGTALK_AGENT_ID', '')
|
||||
|
||||
# for 10.0 or later
|
||||
|
||||
# base setting
|
||||
DINGTALK_APP_KEY = getattr(settings, 'DINGTALK_APP_KEY', '')
|
||||
DINGTALK_APP_SECRET = getattr(settings, 'DINGTALK_APP_SECRET', '')
|
||||
|
||||
# oauth login
|
||||
DINGTALK_OAUTH_RESPONSE_TYPE = getattr(settings, 'DINGTALK_OAUTH_RESPONSE_TYPE', 'code')
|
||||
DINGTALK_OAUTH_SCOPE = getattr(settings, 'DINGTALK_OAUTH_SCOPE', 'openid')
|
||||
DINGTALK_OAUTH_PROMPT = getattr(settings, 'DINGTALK_OAUTH_PROMPT', 'consent')
|
||||
DINGTALK_OAUTH_AUTH_URL = getattr(settings, 'DINGTALK_OAUTH_AUTH_URL', 'https://login.dingtalk.com/oauth2/auth')
|
||||
DINGTALK_OAUTH_GRANT_TYPE = getattr(settings, 'DINGTALK_OAUTH_GRANT_TYPE', 'authorization_code')
|
||||
DINGTALK_OAUTH_USER_ACCESS_TOKEN_URL = getattr(settings,
|
||||
'DINGTALK_OAUTH_USER_ACCESS_TOKEN_URL',
|
||||
'https://api.dingtalk.com/v1.0/oauth2/userAccessToken')
|
||||
DINGTALK_OAUTH_CREATE_UNKNOWN_USER = getattr(settings, 'DINGTALK_OAUTH_CREATE_UNKNOWN_USER', True)
|
||||
DINGTALK_OAUTH_ACTIVATE_USER_AFTER_CREATION = getattr(settings, 'DINGTALK_OAUTH_ACTIVATE_USER_AFTER_CREATION', True)
|
||||
|
||||
DINGTALK_GET_USER_INFO_URL = getattr(settings,
|
||||
'DINGTALK_GET_USER_INFO_URL',
|
||||
'https://api.dingtalk.com/v1.0/contact/users/')
|
||||
DINGTALK_GET_ORGAPP_TOKEN_URL = getattr(settings,
|
||||
'DINGTALK_GET_ORGAPP_TOKEN_URL',
|
||||
'https://oapi.dingtalk.com/gettoken')
|
||||
DINGTALK_TOPAPI_GET_USERID_BY_UNIONID_URL = getattr(settings,
|
||||
'DINGTALK_TOPAPI_GET_USERID_BY_UNIONID_URL',
|
||||
'https://oapi.dingtalk.com/topapi/user/getbyunionid')
|
||||
DINGTALK_TOPAPI_GET_DETAILED_USER_INFO_URL = getattr(settings,
|
||||
'DINGTALK_TOPAPI_GET_DETAILED_USER_INFO_URL',
|
||||
'https://oapi.dingtalk.com/topapi/v2/user/get')
|
||||
|
||||
|
||||
# for 9.0 or before
|
||||
DINGTALK_GET_USERID_BY_UNIONID = getattr(settings, 'DINGTALK_GET_USERID_BY_UNIONID', 'https://oapi.dingtalk.com/user/getUseridByUnionid')
|
||||
|
||||
# for dingtalk qr connect
|
||||
@@ -28,6 +65,3 @@ DINGTALK_DEPARTMENT_USER_SIZE = 100
|
||||
DINGTALK_MESSAGE_SEND_TO_CONVERSATION_URL = getattr(settings, 'DINGTALK_MESSAGE_SEND_TO_CONVERSATION_URL', 'https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2')
|
||||
|
||||
DINGTALK_GET_DETAILED_USER_INFO_URL = getattr(settings, 'DINGTALK_GET_DETAILED_USER_INFO_URL', 'https://oapi.dingtalk.com/user/get')
|
||||
|
||||
# constants
|
||||
DINGTALK_PROVIDER = 'dingtalk'
|
||||
|
@@ -1,9 +1,17 @@
|
||||
import urllib
|
||||
import logging
|
||||
import requests
|
||||
|
||||
from django.core.cache import cache
|
||||
from seahub.utils import normalize_cache_key
|
||||
|
||||
# for 10.0 or later
|
||||
from seahub.dingtalk.settings import DINGTALK_APP_KEY, DINGTALK_APP_SECRET, \
|
||||
DINGTALK_GET_ORGAPP_TOKEN_URL, \
|
||||
DINGTALK_TOPAPI_GET_USERID_BY_UNIONID_URL, \
|
||||
DINGTALK_TOPAPI_GET_DETAILED_USER_INFO_URL
|
||||
|
||||
# for 9.0 or before
|
||||
from seahub.dingtalk.settings import DINGTALK_DEPARTMENT_APP_KEY, \
|
||||
DINGTALK_DEPARTMENT_APP_SECRET, \
|
||||
DINGTALK_DEPARTMENT_GET_ACCESS_TOKEN_URL, \
|
||||
@@ -12,6 +20,87 @@ from seahub.dingtalk.settings import DINGTALK_DEPARTMENT_APP_KEY, \
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# for 10.0 or later
|
||||
def dingtalk_get_orgapp_token():
|
||||
"""
|
||||
https://open.dingtalk.com/document/orgapp/obtain-orgapp-token
|
||||
"""
|
||||
|
||||
cache_key = normalize_cache_key('DINGTALK_ORGAPP_TOKEN')
|
||||
access_token = cache.get(cache_key, None)
|
||||
if access_token:
|
||||
return access_token
|
||||
|
||||
data = {
|
||||
'appkey': DINGTALK_APP_KEY,
|
||||
'appsecret': DINGTALK_APP_SECRET,
|
||||
}
|
||||
resp_json = requests.get(DINGTALK_GET_ORGAPP_TOKEN_URL,
|
||||
params=data).json()
|
||||
|
||||
access_token = resp_json.get('access_token', '')
|
||||
if not access_token:
|
||||
logger.warning('failed to get dingtalk access_token')
|
||||
logger.warning(DINGTALK_GET_ORGAPP_TOKEN_URL)
|
||||
logger.warning(data)
|
||||
logger.warning(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_new(union_id):
|
||||
"""
|
||||
https://open.dingtalk.com/document/orgapp/query-a-user-by-the-union-id
|
||||
"""
|
||||
|
||||
cache_key = normalize_cache_key('DINGTALK_UNION_ID_%s_TO_USER_ID' % union_id)
|
||||
user_id = cache.get(cache_key, None)
|
||||
if user_id:
|
||||
return user_id
|
||||
|
||||
access_token = dingtalk_get_orgapp_token()
|
||||
|
||||
parameters = {'access_token': access_token}
|
||||
data = {'unionid': union_id}
|
||||
|
||||
url = DINGTALK_TOPAPI_GET_USERID_BY_UNIONID_URL + '?' + urllib.parse.urlencode(parameters)
|
||||
resp_json = requests.post(url, data=data).json()
|
||||
|
||||
result = resp_json.get('result', {})
|
||||
user_id = result.get('userid')
|
||||
|
||||
if not user_id:
|
||||
logger.warning('failed to get userid by unionid: %s' % union_id)
|
||||
logger.warning(DINGTALK_TOPAPI_GET_USERID_BY_UNIONID_URL)
|
||||
logger.warning(data)
|
||||
logger.warning(resp_json)
|
||||
return ''
|
||||
|
||||
cache.set(cache_key, user_id)
|
||||
|
||||
return user_id
|
||||
|
||||
|
||||
def dingtalk_get_detailed_user_info_new(user_id):
|
||||
"""
|
||||
https://open.dingtalk.com/document/orgapp/query-user-details
|
||||
"""
|
||||
access_token = dingtalk_get_orgapp_token()
|
||||
|
||||
parameters = {
|
||||
'access_token': access_token,
|
||||
}
|
||||
data = {'userid': user_id}
|
||||
|
||||
url = DINGTALK_TOPAPI_GET_DETAILED_USER_INFO_URL + '?' + urllib.parse.urlencode(parameters)
|
||||
return requests.post(url, data=data).json()
|
||||
|
||||
|
||||
# for 9.0 or before
|
||||
def dingtalk_get_access_token():
|
||||
|
||||
cache_key = normalize_cache_key('DINGTALK_ACCESS_TOKEN')
|
||||
|
@@ -18,15 +18,26 @@ from seahub.api2.utils import get_api_token
|
||||
from seahub import auth
|
||||
from seahub.profile.models import Profile
|
||||
from seahub.utils import render_error, get_site_scheme_and_netloc
|
||||
from seahub.utils.auth import gen_user_virtual_id
|
||||
from seahub.utils.auth import gen_user_virtual_id, VIRTUAL_ID_EMAIL_DOMAIN
|
||||
from seahub.base.accounts import User
|
||||
from seahub.auth.models import SocialAuthUser
|
||||
from seahub.auth.decorators import login_required
|
||||
from seahub.dingtalk.utils import dingtalk_get_detailed_user_info
|
||||
from seahub.dingtalk.utils import dingtalk_get_detailed_user_info, \
|
||||
dingtalk_get_orgapp_token, dingtalk_get_userid_by_unionid_new, \
|
||||
dingtalk_get_detailed_user_info_new
|
||||
|
||||
from seahub.dingtalk.settings import ENABLE_DINGTALK, \
|
||||
DINGTALK_QR_CONNECT_APP_ID, DINGTALK_QR_CONNECT_APP_SECRET, \
|
||||
DINGTALK_QR_CONNECT_AUTHORIZATION_URL, \
|
||||
from seahub.dingtalk.settings import ENABLE_DINGTALK
|
||||
|
||||
# for 10.0 or later
|
||||
from seahub.dingtalk.settings import DINGTALK_APP_KEY, DINGTALK_APP_SECRET, \
|
||||
DINGTALK_OAUTH_RESPONSE_TYPE, DINGTALK_OAUTH_SCOPE, \
|
||||
DINGTALK_OAUTH_PROMPT, DINGTALK_OAUTH_AUTH_URL, \
|
||||
DINGTALK_OAUTH_GRANT_TYPE, DINGTALK_OAUTH_USER_ACCESS_TOKEN_URL, \
|
||||
DINGTALK_GET_USER_INFO_URL
|
||||
|
||||
# for 9.0 or before
|
||||
from seahub.dingtalk.settings import DINGTALK_QR_CONNECT_APP_ID, \
|
||||
DINGTALK_QR_CONNECT_APP_SECRET, DINGTALK_QR_CONNECT_AUTHORIZATION_URL, \
|
||||
DINGTALK_QR_CONNECT_USER_INFO_URL, DINGTALK_QR_CONNECT_RESPONSE_TYPE, \
|
||||
DINGTALK_QR_CONNECT_SCOPE, DINGTALK_QR_CONNECT_LOGIN_REMEMBER_ME
|
||||
|
||||
@@ -38,6 +49,10 @@ def dingtalk_login(request):
|
||||
if not ENABLE_DINGTALK:
|
||||
return render_error(request, _('Error, please contact administrator.'))
|
||||
|
||||
# for 10.0 or later
|
||||
if DINGTALK_APP_KEY and DINGTALK_APP_SECRET:
|
||||
return dingtalk_login_new(request)
|
||||
|
||||
state = str(uuid.uuid4())
|
||||
request.session['dingtalk_login_state'] = state
|
||||
request.session['dingtalk_login_redirect'] = request.GET.get(auth.REDIRECT_FIELD_NAME, '/')
|
||||
@@ -58,6 +73,10 @@ def dingtalk_callback(request):
|
||||
if not ENABLE_DINGTALK:
|
||||
return render_error(request, _('Error, please contact administrator.'))
|
||||
|
||||
# for 10.0 or later
|
||||
if DINGTALK_APP_KEY and DINGTALK_APP_SECRET:
|
||||
return dingtalk_callback_new(request)
|
||||
|
||||
state = request.GET.get('state', '')
|
||||
if not state or state != request.session.get('dingtalk_login_state', ''):
|
||||
logger.error('invalid state')
|
||||
@@ -141,6 +160,10 @@ def dingtalk_connect(request):
|
||||
if not ENABLE_DINGTALK:
|
||||
return render_error(request, _('Error, please contact administrator.'))
|
||||
|
||||
# for 10.0 or later
|
||||
if DINGTALK_APP_KEY and DINGTALK_APP_SECRET:
|
||||
return dingtalk_connect_new(request)
|
||||
|
||||
state = str(uuid.uuid4())
|
||||
request.session['dingtalk_connect_state'] = state
|
||||
request.session['dingtalk_connect_redirect'] = request.GET.get(auth.REDIRECT_FIELD_NAME, '/')
|
||||
@@ -162,6 +185,10 @@ def dingtalk_connect_callback(request):
|
||||
if not ENABLE_DINGTALK:
|
||||
return render_error(request, _('Error, please contact administrator.'))
|
||||
|
||||
# for 10.0 or later
|
||||
if DINGTALK_APP_KEY and DINGTALK_APP_SECRET:
|
||||
return dingtalk_connect_callback_new(request)
|
||||
|
||||
state = request.GET.get('state', '')
|
||||
if not state or state != request.session.get('dingtalk_connect_state', ''):
|
||||
logger.error('invalid state')
|
||||
@@ -216,8 +243,7 @@ def dingtalk_connect_callback(request):
|
||||
profile.contact_email = contact_email
|
||||
profile.save()
|
||||
|
||||
response = HttpResponseRedirect(request.session['dingtalk_connect_redirect'])
|
||||
return response
|
||||
return HttpResponseRedirect(request.session['dingtalk_connect_redirect'])
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -227,6 +253,252 @@ def dingtalk_disconnect(request):
|
||||
return render_error(request, _('Error, please contact administrator.'))
|
||||
|
||||
username = request.user.username
|
||||
if username.endswith(VIRTUAL_ID_EMAIL_DOMAIN):
|
||||
Profile.objects.filter(user=username).delete()
|
||||
|
||||
SocialAuthUser.objects.delete_by_username_and_provider(username, 'dingtalk')
|
||||
response = HttpResponseRedirect(request.GET.get(auth.REDIRECT_FIELD_NAME, '/'))
|
||||
|
||||
return HttpResponseRedirect(request.GET.get(auth.REDIRECT_FIELD_NAME, '/'))
|
||||
|
||||
|
||||
# for 10.0 or later
|
||||
def dingtalk_login_new(request):
|
||||
"""
|
||||
https://open.dingtalk.com/document/orgapp/sso-overview
|
||||
"""
|
||||
|
||||
state = str(uuid.uuid4())
|
||||
request.session['dingtalk_login_state'] = state
|
||||
request.session['dingtalk_login_redirect'] = request.GET.get(auth.REDIRECT_FIELD_NAME, '/')
|
||||
|
||||
data = {
|
||||
'redirect_uri': get_site_scheme_and_netloc() + reverse('dingtalk_callback'),
|
||||
'response_type': DINGTALK_OAUTH_RESPONSE_TYPE,
|
||||
'client_id': DINGTALK_APP_KEY,
|
||||
'scope': DINGTALK_OAUTH_SCOPE,
|
||||
'state': state,
|
||||
'prompt': DINGTALK_OAUTH_PROMPT,
|
||||
}
|
||||
|
||||
url = DINGTALK_OAUTH_AUTH_URL + '?' + urllib.parse.urlencode(data)
|
||||
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
def dingtalk_callback_new(request):
|
||||
|
||||
state = request.GET.get('state', '')
|
||||
if not state or state != request.session.get('dingtalk_login_state', ''):
|
||||
logger.error('invalid state')
|
||||
return render_error(request, _('Error, please contact administrator.'))
|
||||
|
||||
def get_oauth_access_token(code):
|
||||
"""
|
||||
https://open.dingtalk.com/document/orgapp/sso-overview
|
||||
"""
|
||||
data = {
|
||||
"clientId": DINGTALK_APP_KEY,
|
||||
"code": code,
|
||||
"clientSecret": DINGTALK_APP_SECRET,
|
||||
"grantType": DINGTALK_OAUTH_GRANT_TYPE,
|
||||
}
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
|
||||
access_token_resp = requests.post(DINGTALK_OAUTH_USER_ACCESS_TOKEN_URL,
|
||||
headers=headers,
|
||||
data=json.dumps(data))
|
||||
|
||||
return access_token_resp.json().get('accessToken')
|
||||
|
||||
code = request.GET.get('authCode')
|
||||
oauth_access_token = get_oauth_access_token(code)
|
||||
|
||||
def get_user_info(oauth_access_token, union_id='me'):
|
||||
"""
|
||||
https://open.dingtalk.com/document/orgapp/dingtalk-retrieve-user-information#
|
||||
"""
|
||||
|
||||
user_info_url = urllib.parse.urljoin(DINGTALK_GET_USER_INFO_URL, union_id)
|
||||
user_info_resp = requests.get(user_info_url,
|
||||
headers={'x-acs-dingtalk-access-token': oauth_access_token})
|
||||
# {
|
||||
# 'avatarUrl': 'https://static-legacy.dingtalk.com/media/lADPDgQ9rt4yNOLNAjDNAjA_560_560.jpg',
|
||||
# 'mobile': '15313912424',
|
||||
# 'nick': 'lian',
|
||||
# 'openId': 'h1Nar64KnUuY40iiajR3cXAiEiE',
|
||||
# 'stateCode': '86',
|
||||
# 'unionId': '3os80f94Zf4oeiPOpiSiSgiigQiEiE'
|
||||
# }
|
||||
return user_info_resp.json()
|
||||
|
||||
user_info = get_user_info(oauth_access_token)
|
||||
|
||||
# seahub authenticate user
|
||||
if 'unionId' not in user_info:
|
||||
logger.error('Required user info not found.')
|
||||
logger.error(user_info)
|
||||
return render_error(request, _('Error, please contact administrator.'))
|
||||
|
||||
union_id = user_info['unionId']
|
||||
auth_user = SocialAuthUser.objects.get_by_provider_and_uid('dingtalk', union_id)
|
||||
if auth_user:
|
||||
email = auth_user.username
|
||||
else:
|
||||
email = gen_user_virtual_id()
|
||||
SocialAuthUser.objects.add(email, 'dingtalk', union_id)
|
||||
|
||||
try:
|
||||
user = auth.authenticate(remote_user=email)
|
||||
except User.DoesNotExist:
|
||||
user = None
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return render_error(request, _('Error, please contact administrator.'))
|
||||
|
||||
if not user or not user.is_active:
|
||||
return render_error(request, _('User %s not found or inactive.') % email)
|
||||
|
||||
# User is valid. Set request.user and persist user in the session
|
||||
# by logging the user in.
|
||||
request.user = user
|
||||
request.session['remember_me'] = True
|
||||
auth.login(request, user)
|
||||
|
||||
# update user's profile
|
||||
profile = Profile.objects.get_profile_by_user(email)
|
||||
if not profile:
|
||||
profile = Profile(user=email)
|
||||
|
||||
name = user_info['nick'] if 'nick' in user_info else ''
|
||||
if name:
|
||||
profile.nickname = name.strip()
|
||||
profile.save()
|
||||
|
||||
try:
|
||||
user_id = dingtalk_get_userid_by_unionid_new(union_id)
|
||||
detailed_user_info = dingtalk_get_detailed_user_info_new(user_id)
|
||||
contact_email = detailed_user_info.get('result', {}).get('email', '')
|
||||
if contact_email:
|
||||
profile.contact_email = contact_email
|
||||
profile.save()
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
# generate auth token for Seafile client
|
||||
api_token = get_api_token(request)
|
||||
|
||||
# redirect user to home page
|
||||
response = HttpResponseRedirect(request.session.get('dingtalk_login_redirect', '/'))
|
||||
response.set_cookie('seahub_auth', email + '@' + api_token.key)
|
||||
return response
|
||||
|
||||
|
||||
def dingtalk_connect_new(request):
|
||||
"""
|
||||
https://open.dingtalk.com/document/orgapp/sso-overview
|
||||
"""
|
||||
|
||||
state = str(uuid.uuid4())
|
||||
request.session['dingtalk_connect_state'] = state
|
||||
request.session['dingtalk_connect_redirect'] = request.GET.get(auth.REDIRECT_FIELD_NAME, '/')
|
||||
|
||||
data = {
|
||||
'redirect_uri': get_site_scheme_and_netloc() + reverse('dingtalk_connect_callback'),
|
||||
'response_type': DINGTALK_OAUTH_RESPONSE_TYPE,
|
||||
'client_id': DINGTALK_APP_KEY,
|
||||
'scope': DINGTALK_OAUTH_SCOPE,
|
||||
'state': state,
|
||||
'prompt': DINGTALK_OAUTH_PROMPT,
|
||||
}
|
||||
|
||||
url = DINGTALK_OAUTH_AUTH_URL + '?' + urllib.parse.urlencode(data)
|
||||
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
@login_required
|
||||
def dingtalk_connect_callback_new(request):
|
||||
|
||||
state = request.GET.get('state', '')
|
||||
if not state or state != request.session.get('dingtalk_connect_state', ''):
|
||||
logger.error('invalid state')
|
||||
return render_error(request, _('Error, please contact administrator.'))
|
||||
|
||||
def get_oauth_access_token(code):
|
||||
"""
|
||||
https://open.dingtalk.com/document/orgapp/sso-overview
|
||||
"""
|
||||
data = {
|
||||
"clientId": DINGTALK_APP_KEY,
|
||||
"code": code,
|
||||
"clientSecret": DINGTALK_APP_SECRET,
|
||||
"grantType": DINGTALK_OAUTH_GRANT_TYPE,
|
||||
}
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
|
||||
access_token_resp = requests.post(DINGTALK_OAUTH_USER_ACCESS_TOKEN_URL,
|
||||
headers=headers,
|
||||
data=json.dumps(data))
|
||||
|
||||
return access_token_resp.json().get('accessToken')
|
||||
|
||||
code = request.GET.get('authCode')
|
||||
oauth_access_token = get_oauth_access_token(code)
|
||||
|
||||
def get_user_info(oauth_access_token, union_id='me'):
|
||||
"""
|
||||
https://open.dingtalk.com/document/orgapp/dingtalk-retrieve-user-information#
|
||||
"""
|
||||
|
||||
user_info_url = urllib.parse.urljoin(DINGTALK_GET_USER_INFO_URL, union_id)
|
||||
user_info_resp = requests.get(user_info_url,
|
||||
headers={'x-acs-dingtalk-access-token': oauth_access_token})
|
||||
# {
|
||||
# 'avatarUrl': 'https://static-legacy.dingtalk.com/media/lADPDgQ9rt4yNOLNAjDNAjA_560_560.jpg',
|
||||
# 'mobile': '15313912424',
|
||||
# 'nick': 'lian',
|
||||
# 'openId': 'h1Nar64KnUuY40iiajR3cXAiEiE',
|
||||
# 'stateCode': '86',
|
||||
# 'unionId': '3os80f94Zf4oeiPOpiSiSgiigQiEiE'
|
||||
# }
|
||||
return user_info_resp.json()
|
||||
|
||||
user_info = get_user_info(oauth_access_token)
|
||||
|
||||
# seahub authenticate user
|
||||
if 'unionId' not in user_info:
|
||||
logger.error('Required user info not found.')
|
||||
logger.error(user_info)
|
||||
return render_error(request, _('Error, please contact administrator.'))
|
||||
|
||||
union_id = user_info['unionId']
|
||||
username = request.user.username
|
||||
auth_user = SocialAuthUser.objects.get_by_provider_and_uid('dingtalk', union_id)
|
||||
if auth_user:
|
||||
logger.error('dingtalk account already exists %s' % union_id)
|
||||
return render_error(request, '出错了,此钉钉账号已被绑定')
|
||||
|
||||
SocialAuthUser.objects.add(username, 'dingtalk', union_id)
|
||||
|
||||
# update user's profile
|
||||
profile = Profile.objects.get_profile_by_user(username)
|
||||
if not profile:
|
||||
profile = Profile(user=username)
|
||||
|
||||
name = user_info['nick'] if 'nick' in user_info else ''
|
||||
if name:
|
||||
profile.nickname = name.strip()
|
||||
profile.save()
|
||||
|
||||
try:
|
||||
user_id = dingtalk_get_userid_by_unionid_new(union_id)
|
||||
detailed_user_info = dingtalk_get_detailed_user_info_new(user_id)
|
||||
contact_email = detailed_user_info.get('result', {}).get('email', '')
|
||||
if contact_email:
|
||||
profile.contact_email = contact_email
|
||||
profile.save()
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
response = HttpResponseRedirect(request.session.get('dingtalk_connect_redirect', '/'))
|
||||
return response
|
||||
|
@@ -16,10 +16,20 @@ 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
|
||||
|
||||
# for 10.0 or later
|
||||
from seahub.dingtalk.settings import DINGTALK_APP_KEY, \
|
||||
DINGTALK_APP_SECRET
|
||||
|
||||
if DINGTALK_APP_KEY and DINGTALK_APP_SECRET:
|
||||
from seahub.dingtalk.utils import dingtalk_get_orgapp_token as dingtalk_get_access_token
|
||||
from seahub.dingtalk.utils import dingtalk_get_userid_by_unionid_new as dingtalk_get_userid_by_unionid
|
||||
else:
|
||||
from seahub.dingtalk.utils import dingtalk_get_access_token, dingtalk_get_userid_by_unionid
|
||||
|
||||
|
||||
# Get an instance of a logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -87,7 +97,7 @@ class Command(BaseCommand, CommandLogMixin):
|
||||
}
|
||||
}
|
||||
resp_json = requests.post(self.dingtalk_message_send_to_conversation_url,
|
||||
data=json.dumps(data)).json()
|
||||
data=json.dumps(data)).json()
|
||||
if resp_json.get('errcode') != 0:
|
||||
self.log_info(resp_json)
|
||||
|
||||
|
@@ -8,6 +8,7 @@ from seahub.work_weixin.settings import ENABLE_WORK_WEIXIN
|
||||
from seahub.weixin.settings import ENABLE_WEIXIN
|
||||
from seahub.dingtalk.settings import ENABLE_DINGTALK
|
||||
|
||||
|
||||
class OauthRemoteUserBackend(RemoteUserBackend):
|
||||
"""
|
||||
This backend is to be used in conjunction with the ``RemoteUserMiddleware``
|
||||
@@ -36,10 +37,10 @@ class OauthRemoteUserBackend(RemoteUserBackend):
|
||||
activate_after_creation = WEIXIN_OAUTH_ACTIVATE_USER_AFTER_CREATION
|
||||
|
||||
if ENABLE_DINGTALK:
|
||||
from seahub.dingtalk.settings import DINGTALK_QR_CONNECT_CREATE_UNKNOWN_USER, \
|
||||
DINGTALK_QR_CONNECT_ACTIVATE_USER_AFTER_CREATION
|
||||
create_unknown_user = DINGTALK_QR_CONNECT_CREATE_UNKNOWN_USER
|
||||
activate_after_creation = DINGTALK_QR_CONNECT_ACTIVATE_USER_AFTER_CREATION
|
||||
from seahub.dingtalk.settings import DINGTALK_OAUTH_CREATE_UNKNOWN_USER, \
|
||||
DINGTALK_OAUTH_ACTIVATE_USER_AFTER_CREATION
|
||||
create_unknown_user = DINGTALK_OAUTH_CREATE_UNKNOWN_USER
|
||||
activate_after_creation = DINGTALK_OAUTH_ACTIVATE_USER_AFTER_CREATION
|
||||
|
||||
def get_user(self, username):
|
||||
try:
|
||||
|
Reference in New Issue
Block a user