import flask
import raven.breadcrumbs
from raven.contrib.flask import Sentry

from .auth import current_user
from . import current_app


class PillarSentry(Sentry):
    """Flask Sentry with Pillar support.

    This is mostly for obtaining user information on API calls,
    and for preventing the auth tokens to be logged as user ID.
    """

    def init_app(self, app, *args, **kwargs):
        super().init_app(app, *args, **kwargs)

        flask.request_started.connect(self.__add_sentry_breadcrumbs, self)

    def __add_sentry_breadcrumbs(self, sender, **extra):
        raven.breadcrumbs.record(
            message='Request started',
            category='http',
            data={'url': flask.request.url}
        )

    def get_user_info(self, request):
        user_info = super().get_user_info(request)

        # The auth token is stored as the user ID in the flask_login
        # current_user object, so don't send that to Sentry.
        user_info.pop('id', None)

        if len(user_info) > 1:
            # Sentry always includes the IP address, but when they find a
            # logged-in user, they add more info. In that case we're done.
            return user_info

        # This is pretty much a copy-paste from Sentry, except that it uses
        # pillar.auth.current_user instead.
        try:
            if not current_user.is_authenticated:
                return user_info
        except AttributeError:
            # HACK: catch the attribute error thrown by flask-login is not attached
            # >   current_user = LocalProxy(lambda: _request_ctx_stack.top.user)
            # E   AttributeError: 'RequestContext' object has no attribute 'user'
            return user_info

        if 'SENTRY_USER_ATTRS' in current_app.config:
            for attr in current_app.config['SENTRY_USER_ATTRS']:
                if hasattr(current_user, attr):
                    user_info[attr] = getattr(current_user, attr)

        return user_info
