def call_vk_method(method, **kwargs): response = requests.get(VK_API_URL + method + u'?' + u'&'.join([u"%s=%s" % (k, v) for k, v in kwargs.items()])) if response.status_code != 200: raise errors.SocialAuthError() data = response.json() if not data: if VkBackend.is_token_expired(data): raise errors.RenewAuthTokenError() else: raise errors.SocialAuthError('Failed to decode server answer') return data
def get_user_data(config, access_token): vk_api_version = "3" data = VkBackend.call_vk_method('users.get', v=vk_api_version, access_token=access_token) if 'response' not in data: raise errors.SocialAuthError('Failed to decode server answer. data=%s; api version=%s; access_token=%s' % ( data, vk_api_version, access_token)) user_data = data['response'][0] try: user_id = int(user_data['uid']) except ValueError: raise errors.SocialAuthError('Failed to decode server answer. data=%s; api version=%s; access_token=%s' % ( data, vk_api_version, access_token)) return dict(id=user_id)
def new_post(post_content, auth_user, config, link_to_attach=None): link = SocialUserLink.query.filter_by(user=auth_user, service_id=SocialServiceEnum.SS_VK).first() if not link or not link.access_token: raise errors.SocialAuthError() try: params = dict(v=config['vk_api_version'], access_token=link.access_token, message=post_content) if link_to_attach: params['attachments'] = link_to_attach response_data = VkBackend.call_vk_method('wall.post', **params) except errors.RenewAuthTokenError, exc: link.access_token = "" sqldb.session.commit() raise
class VkBackend(SocialBackend): @staticmethod def is_token_expired(data): return 'error' in data and 'error_code' in data['error'] and data['error']['error_code'] in (2, 4, 5, 7) @staticmethod def call_vk_method(method, **kwargs): response = requests.get(VK_API_URL + method + u'?' + u'&'.join([u"%s=%s" % (k, v) for k, v in kwargs.items()])) if response.status_code != 200: raise errors.SocialAuthError() data = response.json() if not data: if VkBackend.is_token_expired(data): raise errors.RenewAuthTokenError() else: raise errors.SocialAuthError('Failed to decode server answer') return data @staticmethod def get_user_data(config, access_token): vk_api_version = "3" data = VkBackend.call_vk_method('users.get', v=vk_api_version, access_token=access_token) if 'response' not in data: raise errors.SocialAuthError('Failed to decode server answer. data=%s; api version=%s; access_token=%s' % ( data, vk_api_version, access_token)) user_data = data['response'][0] try: user_id = int(user_data['uid']) except ValueError: raise errors.SocialAuthError('Failed to decode server answer. data=%s; api version=%s; access_token=%s' % ( data, vk_api_version, access_token)) return dict(id=user_id) @staticmethod def get_user_link(social_uid): return SocialUserLink.query.filter_by(uid=str(social_uid), service_id=SocialServiceEnum.SS_VK).first() @staticmethod def make_link(access_token, social_uid, auth_user, config): link = SocialUserLink( uid=social_uid, user=auth_user, service_id=SocialServiceEnum.SS_VK, access_token=access_token ) sqldb.session.add(link) sqldb.session.commit() return link @staticmethod def get_token_url(config, next_page="/"): if next_page.startswith("/"): next_page = next_page[1:] vk_api_version = config['vk_api_version'] permissions = config['vk_app_permissions'] vk_app_id = config['vk_app_id'] redirect_url = "%s://%s%s" % ( config['WEB_SCHEMA'], config['api_url'], config['vk_auth_redirect_url'] + next_page) return "https://oauth.vk.com/authorize?client_id=%d&scope=%d&redirect_uri=%s&display=page&v=%s&response_type=code" % ( vk_app_id, permissions, redirect_url, vk_api_version) @staticmethod def new_post(post_content, auth_user, config, link_to_attach=None): link = SocialUserLink.query.filter_by(user=auth_user, service_id=SocialServiceEnum.SS_VK).first() if not link or not link.access_token: raise errors.SocialAuthError() try: params = dict(v=config['vk_api_version'], access_token=link.access_token, message=post_content) if link_to_attach: params['attachments'] = link_to_attach response_data = VkBackend.call_vk_method('wall.post', **params) except errors.RenewAuthTokenError, exc: link.access_token = "" sqldb.session.commit() raise if 'response' not in response_data: raise errors.SocialAuthError('Failed to decode server answer') else: post_data = dict(id=response_data['response']['post_id']) return post_data
def login_external(social_network=None, next_page=""): class MyResp(Response): def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False): self.__name = key self.__val = value super(MyResp, self).set_cookie(key, value, max_age, expires, path, domain, secure, httponly) try: code = request.args['code'] except Exception: if 'error' in request.args: html = u"""<html><head></head><body><script>window.location.href = "/";</script></body></html>""" my_resp = MyResp(html, status=200, content_type="text/html; charset=utf-8") return my_resp raise errors.InvalidParameterValue('code') if social_network not in ('facebook', 'vk', 'google'): raise errors.InvalidParameterValue('social_network') backend = SocialServiceBackends.backends.get(social_network) if not backend: raise errors.InvalidParameterValue('social_network') config = current_app.config if backend: if '?' in next_page: next_page = next_page.split('?')[0] current_app.logger.debug(u"2 redirect url: %s" % next_page) access_token, ext_data = backend.get_token(code, config, next_page=next_page) if not access_token: raise errors.SocialAuthError() user_data = backend.get_user_data(config, access_token) social_uid = user_data.get('id') if not social_uid: raise errors.SocialAuthError() social_service_user_link = backend.get_user_link(unicode(social_uid)) if social_service_user_link: user = social_service_user_link.user else: ext_data = ext_data or {} if 'email' not in ext_data: ext_data = backend.get_user_data(config, access_token) user, user_profile = UserManager.create_user(access_token, "", ext_data.get('email', ""), "", "", "", "", social_network, email_is_social=True) old_user_id = current_user.id if ( current_user and not current_user.is_anonymous and current_user.temporal) else None if old_user_id: new_user_id = user.id change_account_data_owner(old_user_id, new_user_id) google_client_id = request.cookies.get('_ga_cid') if google_client_id and not user.temporal: metrics.update_user_info(user, google_client_id=google_client_id) login_user(user) user.last_login_date = datetime.utcnow() my_resp = MyResp() current_app.session_interface.save_session(current_app, flask.session, my_resp) # noinspection PyUnresolvedReferences html = u""" <html> <head></head> <body> <script> window.location.href = "/%s"; </script> </body> </html> """ % next_page my_resp = MyResp(html, status=200, content_type="text/html; charset=utf-8") return my_resp return {"result": None}
def create_user(cls, social_service_access_token, mobile, email, name, surname, patronymic, password, social_network, email_is_social=False, temp_user=None, is_tester=False): is_temp_user = not mobile and not email email_confirmed = False social_uid = None social_email = '' social_backend = None token = None if social_service_access_token and social_network: token = social_service_access_token social_backend = SocialServiceBackends.backends.get(social_network) if social_backend: social_data = social_backend.get_user_data(cls.__config, token) social_uid = social_data.get('id', None) if not social_data or not social_uid: raise errors.SocialAuthError() social_email = social_data.get('email', None) if social_email: social_email = social_email.lower() social_service_user_link = social_backend.get_user_link(social_uid) if social_service_user_link: user_id = social_service_user_link.auth_user user = AuthUser.query.filter_by(id=user_id) return user, False email = email.lower() if email else u'' if email: if email_is_social or (social_email and email == social_email): email_confirmed = True elif not email and not mobile and social_backend: email = social_email if email: email_confirmed = True current_user = (AuthUser.query.filter_by(email=unicode(email)).first() if email else AuthUser.query.filter_by(mobile=unicode(mobile)).first() if mobile else None) if current_user: if email: if social_email and social_uid: if current_user.email_confirmed: social_backend.make_link(token, social_uid, current_user, cls.__config) return current_user, False else: email = u'' email_confirmed = False else: raise errors.DuplicateEmail() else: raise errors.DuplicateMobile() # Creating new auth user record user = temp_user or AuthUser(uuid=unicode(ObjectId())) user.email_confirmed = email_confirmed user.mobile_confirmed = False user.is_tester = is_tester if email_confirmed: user.email = email user.password = unicode(encrypt_password(password)) if password else None user.signup_date = datetime.utcnow() user.enabled = True user.email = unicode(email) if email else None user.mobile = unicode(mobile) if mobile else None user.name = unicode(name) user.surname = unicode(surname) user.patronymic = unicode(patronymic) user.temporal = is_temp_user try: db.session.add(user) except Exception, exc: cls.__logger.error('Failed to add user to DB: %s' % str(exc)) db.session.rollback() raise