def handler_RequestException(self, request, exception): context = {} msg = u'账号登陆失败' long_message = u'登陆失败,请稍后重试。' context['retry_url'] = '' context['failed_title'] = msg context['failed_content'] = long_message track_log(request, 'oauth.user.login_failure', { 'success': False, 'field': 'incorrect.{}'.format("RequestException"), 'context': context, }) return render_to_response('xuetangx/oauth/failed.html', context)
def handler_AuthAlreadyAssociated(self, request, exception): context = {} provider = PROVIDER_MAPPER.get(exception.backend.name, {}).get('platform', u'三方') msg = u'{provider}账号绑定失败'.format(provider=provider) reason = u'此{provider}账号已绑定过其他学堂账号,或者此学堂账号已经绑定过其他{provider}账号'.format(provider=provider) context['failed_title'] = msg context['failed_content'] = reason track_log(request, 'oauth.user.login_failure', { 'success': False, 'field': 'duplicate.{}'.format(provider), 'context': context, }) return render_to_response('xuetangx/oauth/failed.html', context)
def handler_AuthException(self, request, exception): context = {} msg = u'账号登陆失败' long_message = u'登陆失败,请稍后重试' context['failed_title'] = msg context['failed_content'] = long_message context['retry_url'] = '/dashboard' context['retry_content'] = u'使用邮箱密码登陆' provider = PROVIDER_MAPPER.get(exception.backend.name, {}).get('platform', u'三方') track_log(request, 'oauth.user.login_failure', { 'success': False, 'field': 'incorrect.{}'.format(provider), 'context': context, }) return render_to_response('xuetangx/oauth/failed.html', context)
def authentication_success(request): ''' 新用户注册时 用户直接走oauth后通过python-social-auth的auth后,成功会回调到此处, 此时django的用户应该是未登录状态 request.user.is_authenticated() is False ''' detail = request.session.get('authentication_user_detail') inviter_id = request.session.get('inviter_id') provider = detail['social_provider'] strategy = get_strategy(provider) enrollment_action = request.session.get('enrollment_action') course_id = request.session.get('course_id') user, _created = _get_or_create_oauth_user(strategy, detail, request) # 如果有邀请 if inviter_id: _create_user_invite(inviter_id, user) login(request, user) user_profile = user.profile user_profile.last_login_ip = request.META.get('REMOTE_ADDR', None) user_profile.save() # 如果用户没有登录就选课,并且这时候选择的是oauth,尝试enroll课程 if enrollment_action: request.method = 'POST' request.POST = request.POST.copy() request.POST['enrollment_action'] = enrollment_action request.POST['course_id'] = course_id try_change_enrollment(request) next_url = request.session.get('next', '') context = {'next': next_url} track_log(request, 'oauth.user.login_success', { 'success': True, 'uid': user.id, 'provider': strategy.backend.name, }) return render_to_response('xuetangx/oauth/oauth_login_success.html', context)
def _get_or_create_oauth_user(strategy, detail, request=None, mobile_client=False, created_on='web'): ''' strategy -- strategy obj detail -- oauth登录拿到token时的response ''' backend = strategy.backend _created = False uid = get_uid(strategy, detail) # weibo新接口uid改名叫做id if not uid: uid = detail.get('id') # weixin if backend.name in ('weixin', 'weixinapp'): weixin_unionid = detail.get('unionid') if weixin_unionid: weixin_users = UserSocialAuth.objects.filter(weixin_unionid=weixin_unionid).order_by('id') weixin_users_count = weixin_users.count() # 微信只有一个UserSocialAuth时,使用这个 if weixin_users_count == 1: user = weixin_users[0].user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) elif weixin_users_count > 1: # 有web则永远返回第一个web用户 for each in weixin_users: if each.created_on and each.created_on.startswith('web'): user = each.user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) # 否则返回mobile用户 for each in weixin_users: if each.created_on and each.created_on.startswith('mobile'): user = each.user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) # 否则返回weixin app用户(微信服务号活动生成) for each in weixin_users: if each.created_on and each.created_on.startswith('app'): user = each.user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) # 没有第四种逻辑, 但是还是加上吧 user = weixin_users[0].user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) if backend.name == 'chinamobile': extra_data = backend.extra_data(None, uid, detail, {}) phone_number = extra_data.get('phone_number', None) try: user_profile = UserProfile.objects.get(phone_number=phone_number) user = user_profile.user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) except: pass result = social_user(strategy, uid) # 已有账户,直接登录 if result['user']: user = result['user'] # 否则创建用户,之后登录 else: user = User() user.username = str(uuid.uuid4()).replace('-', '')[:20] user.email = None # oauth的自动激活 user.is_active = True user.set_unusable_password() user.save() extra_data = backend.extra_data(user, uid, detail, {}) profile = UserProfile(user=user) nickname = get_validate_nickname(extra_data['username']) oauth_nickname = nickname # 重名加后缀,最多尝试10次 MAX_TRY_TIMES = 10 while MAX_TRY_TIMES: try: UserProfile.objects.get(nickname=nickname) suffix = str(uuid.uuid4().int)[:6] nickname = '{}{}'.format(oauth_nickname, suffix) MAX_TRY_TIMES = MAX_TRY_TIMES - 1 except UserProfile.DoesNotExist: break profile.phone_number = extra_data.get('phone_number', None) profile.nickname = nickname profile.unique_code = profile.get_unique_code() if request: profile.set_register_extra(request=request, cover_data={'channel': backend.name}) if extra_data.get('profile_image_url'): profile.avatar = extra_data['profile_image_url'] if extra_data.get('gender'): profile.gender = extra_data['gender'] if extra_data.get('year_of_birth'): profile.year_of_birth = extra_data['year_of_birth'] if backend.name == 'chinamobile': profile.register_type = 'migu' profile.register_auto = 1 profile.save() # TODO: AuthAlreadyAssociated # 此oauth账号之前已经绑定了学堂在线的账号 new_associate_user(strategy, uid, user, detail, created_on=created_on) _created = True # Track this user register event in oauth if not mobile_client: # do not track api client log 2015.5.26 event_type = 'weixinapp.user.register_success' if created_on == 'weixinapp' else 'oauth.user.register_success' track_log(request, event_type, { 'success': True, 'uid': user.id, 'provider': backend.name, }) user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, _created)
def _get_or_create_oauth_user(strategy, detail, request=None, mobile_client=False, created_on='web'): ''' strategy -- strategy obj detail -- oauth登录拿到token时的response ''' backend = strategy.backend _created = False uid = get_uid(strategy, detail) # weibo新接口uid改名叫做id if not uid: uid = detail.get('id') # weixin if backend.name in ('weixin', 'weixinapp'): weixin_unionid = detail.get('unionid') if weixin_unionid: weixin_users = UserSocialAuth.objects.filter( weixin_unionid=weixin_unionid).order_by('id') weixin_users_count = weixin_users.count() # 微信只有一个UserSocialAuth时,使用这个 if weixin_users_count == 1: user = weixin_users[0].user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) elif weixin_users_count > 1: # 有web则永远返回第一个web用户 for each in weixin_users: if each.created_on and each.created_on.startswith('web'): user = each.user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) # 否则返回mobile用户 for each in weixin_users: if each.created_on and each.created_on.startswith( 'mobile'): user = each.user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) # 否则返回weixin app用户(微信服务号活动生成) for each in weixin_users: if each.created_on and each.created_on.startswith('app'): user = each.user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) # 没有第四种逻辑, 但是还是加上吧 user = weixin_users[0].user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) if backend.name == 'chinamobile': extra_data = backend.extra_data(None, uid, detail, {}) phone_number = extra_data.get('phone_number', None) try: user_profile = UserProfile.objects.get(phone_number=phone_number) user = user_profile.user user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, False) except: pass result = social_user(strategy, uid) # 已有账户,直接登录 if result['user']: user = result['user'] # 否则创建用户,之后登录 else: user = User() user.username = str(uuid.uuid4()).replace('-', '')[:20] user.email = None # oauth的自动激活 user.is_active = True user.set_unusable_password() user.save() extra_data = backend.extra_data(user, uid, detail, {}) profile = UserProfile(user=user) nickname = get_validate_nickname(extra_data['username']) oauth_nickname = nickname # 重名加后缀,最多尝试10次 MAX_TRY_TIMES = 10 while MAX_TRY_TIMES: try: UserProfile.objects.get(nickname=nickname) suffix = str(uuid.uuid4().int)[:6] nickname = '{}{}'.format(oauth_nickname, suffix) MAX_TRY_TIMES = MAX_TRY_TIMES - 1 except UserProfile.DoesNotExist: break profile.phone_number = extra_data.get('phone_number', None) profile.nickname = nickname profile.unique_code = profile.get_unique_code() if request: profile.set_register_extra(request=request, cover_data={'channel': backend.name}) if extra_data.get('profile_image_url'): profile.avatar = extra_data['profile_image_url'] if extra_data.get('gender'): profile.gender = extra_data['gender'] if extra_data.get('year_of_birth'): profile.year_of_birth = extra_data['year_of_birth'] if backend.name == 'chinamobile': profile.register_type = 'migu' profile.register_auto = 1 profile.save() # TODO: AuthAlreadyAssociated # 此oauth账号之前已经绑定了学堂在线的账号 new_associate_user(strategy, uid, user, detail, created_on=created_on) _created = True # Track this user register event in oauth if not mobile_client: # do not track api client log 2015.5.26 event_type = 'weixinapp.user.register_success' if created_on == 'weixinapp' else 'oauth.user.register_success' track_log(request, event_type, { 'success': True, 'uid': user.id, 'provider': backend.name, }) user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return (user, _created)