Пример #1
0
    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
Пример #2
0
    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)
Пример #3
0
    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
Пример #4
0
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
Пример #5
0
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}
Пример #6
0
    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