Пример #1
0
def request_started_handler(sender, **kwargs):
    environ = kwargs.get("environ")
    scope = kwargs.get("scope")

    if environ:
        path = environ["PATH_INFO"]
        cookie_string = environ.get("HTTP_COOKIE")
        remote_ip = environ[REMOTE_ADDR_HEADER]
        method = environ["REQUEST_METHOD"]
        query_string = environ["QUERY_STRING"]

    else:
        method = scope.get("method")
        path = scope.get("path")
        headers = dict(scope.get("headers"))
        cookie_string = headers.get(b"cookie")
        if isinstance(cookie_string, bytes):
            cookie_string = cookie_string.decode("utf-8")
        server = scope.get("server")
        remote_ip = "{s_ip}:{s_port}".format(s_ip=server[0], s_port=server[1])
        query_string = scope.get("query_string")

    if not should_log_url(path):
        return

    # try and get the user from the request; commented for now, may have a bug in this flow.
    user = get_current_user()
    # user = None
    # get the user from cookies
    if not user and cookie_string:
        cookie = SimpleCookie()
        cookie.load(cookie_string)
        session_cookie_name = settings.SESSION_COOKIE_NAME
        if session_cookie_name in cookie:
            session_id = cookie[session_cookie_name].value

            try:
                session = Session.objects.get(session_key=session_id)
            except Session.DoesNotExist:
                session = None

            if session:
                user_id = session.get_decoded().get("_auth_user_id")
                try:
                    user = get_user_model().objects.get(id=user_id)
                except:
                    user = None

    # may want to wrap this in an atomic transaction later
    request_event = audit_logger.request({
        "url": path,
        "method": method,
        "query_string": query_string,
        "user_id": getattr(user, "id", None),
        "remote_ip": remote_ip,
        "created": timezone.now(),
    })
Пример #2
0
def post_delete(sender, instance, using, **kwargs):
    """https://docs.djangoproject.com/es/1.10/ref/signals/#post-delete"""
    try:
        with transaction.atomic(using=using):
            if not should_audit(instance):
                return False

            object_json_repr = serializers.serialize("json", [instance])

            # user
            try:
                user = get_current_user()
                # validate that the user still exists
                user = get_user_model().objects.get(pk=user.pk)
            except:
                user = None

            if isinstance(user, AnonymousUser):
                user = None

            # object id to be used later
            obj_id = instance.pk

            def crud_flow():
                try:
                    with transaction.atomic(using=DATABASE_ALIAS):
                        # crud event
                        crud_event = audit_logger.crud(
                            {
                                "event_type": CRUDEvent.DELETE,
                                "object_repr": str(instance),
                                "object_json_repr": object_json_repr,
                                "object_id": obj_id,
                                "user_id": getattr(user, "id", None),
                                "created": timezone.now(),
                                "user_pk_as_string": str(user.pk) if user else user,
                            }
                        )

                except Exception as e:
                    try:
                        logger.exception(
                            "easy audit had a post_delete exception on CRUDEvent creation. instance: {}, instance pk: {}".format(
                                instance, instance.pk
                            )
                        )
                    except Exception:
                        pass

            if getattr(settings, "TEST", False):
                crud_flow()
            else:
                transaction.on_commit(crud_flow, using=using)
    except Exception:
        logger.exception("easy audit had a post-delete exception.")
Пример #3
0
def pre_save(sender, instance, raw, using, update_fields, **kwargs):
    """https://docs.djangoproject.com/es/1.10/ref/signals/#post-save"""
    if raw:
        # Return if loading Fixtures
        return

    try:
        with transaction.atomic(using=using):
            if not should_audit(instance):
                return False
            try:
                object_json_repr = serializers.serialize("json", [instance])
            except Exception:
                # We need a better way for this to work. ManyToMany will fail on pre_save on create
                return None

            # Determine if the instance is a create
            created = instance.pk is None or instance._state.adding

            # created or updated?
            if not created:
                old_model = sender.objects.get(pk=instance.pk)
                delta = model_delta(old_model, instance)
                if not delta and getattr(
                    settings,
                    "DJANGO_EASY_AUDIT_CRUD_EVENT_NO_CHANGED_FIELDS_SKIP",
                    False,
                ):
                    return False
                changed_fields = json.dumps(delta)
                event_type = CRUDEvent.UPDATE

            # user
            try:
                user = get_current_user()
                # validate that the user still exists
                user = get_user_model().objects.get(pk=user.pk)
            except:
                user = None

            if isinstance(user, AnonymousUser):
                user = None

            # callbacks
            kwargs[
                "request"
            ] = get_current_request()  # make request available for callbacks
            create_crud_event = all(
                callback(
                    instance,
                    object_json_repr,
                    created,
                    raw,
                    using,
                    update_fields,
                    **kwargs
                )
                for callback in CRUD_DIFFERENCE_CALLBACKS
                if callable(callback)
            )
            # create crud event only if all callbacks returned True
            if create_crud_event and not created:

                def crud_flow():
                    try:
                        # atomicity based on the easyaudit database alias
                        with transaction.atomic(using=DATABASE_ALIAS):
                            crud_event = audit_logger.crud(
                                {
                                    "event_type": event_type,
                                    "object_repr": str(instance),
                                    "object_json_repr": object_json_repr,
                                    "changed_fields": changed_fields,
                                    "object_id": instance.pk,
                                    "user_id": getattr(user, "id", None),
                                    "created": timezone.now(),
                                    "user_pk_as_string": str(user.pk) if user else user,
                                }
                            )
                    except Exception as e:
                        try:
                            logger.exception(
                                "easy audit had a pre_save exception on CRUDEvent creation. instance: {}, instance pk: {}".format(
                                    instance, instance.pk
                                )
                            )
                        except Exception:
                            pass

                if getattr(settings, "TEST", False):
                    crud_flow()
                else:
                    transaction.on_commit(crud_flow, using=using)
    except Exception:
        logger.exception("easy audit had a pre-save exception.")
Пример #4
0
def m2m_changed(sender, instance, action, reverse, model, pk_set, using, **kwargs):
    """https://docs.djangoproject.com/es/1.10/ref/signals/#m2m-changed"""
    try:
        with transaction.atomic(using=using):
            if not should_audit(instance):
                return False

            if action not in ("post_add", "post_remove", "post_clear"):
                return False

            object_json_repr = serializers.serialize("json", [instance])

            if reverse:
                event_type = CRUDEvent.M2M_CHANGE_REV
                # add reverse M2M changes to event. must use json lib because
                # django serializers ignore extra fields.
                tmp_repr = json.loads(object_json_repr)

                m2m_rev_field = _m2m_rev_field_name(
                    instance._meta.concrete_model, model
                )
                related_instances = getattr(instance, m2m_rev_field).all()
                related_ids = [r.pk for r in related_instances]

                tmp_repr[0]["m2m_rev_model"] = force_text(model._meta)
                tmp_repr[0]["m2m_rev_pks"] = related_ids
                tmp_repr[0]["m2m_rev_action"] = action
                object_json_repr = json.dumps(tmp_repr)
            else:
                event_type = CRUDEvent.M2M_CHANGE

            # user
            try:
                user = get_current_user()
                # validate that the user still exists
                user = get_user_model().objects.get(pk=user.pk)
            except:
                user = None

            if isinstance(user, AnonymousUser):
                user = None

            def crud_flow():
                try:
                    with transaction.atomic(using=DATABASE_ALIAS):
                        crud_event = audit_logger.crud(
                            {
                                "event_type": event_type,
                                "object_repr": str(instance),
                                "object_json_repr": object_json_repr,
                                "object_id": instance.pk,
                                "user_id": getattr(user, "id", None),
                                "created": timezone.now(),
                                "user_pk_as_string": str(user.pk) if user else user,
                            }
                        )
                except Exception as e:
                    try:
                        logger.exception(
                            "easy audit had a m2m_changed exception on CRUDEvent creation. instance: {}, instance pk: {}".format(
                                instance, instance.pk
                            )
                        )
                    except Exception:
                        pass

            if getattr(settings, "TEST", False):
                crud_flow()
            else:
                transaction.on_commit(crud_flow, using=using)
    except Exception:
        logger.exception("easy audit had an m2m-changed exception.")
Пример #5
0
def post_save(sender, instance, created, raw, using, update_fields, **kwargs):
    """https://docs.djangoproject.com/es/1.10/ref/signals/#post-save"""
    if raw:
        # Return if loading Fixtures
        return

    try:
        with transaction.atomic(using=using):
            if not should_audit(instance):
                return False
            object_json_repr = serializers.serialize("json", [instance])

            # created or updated?
            if created:
                event_type = CRUDEvent.CREATE

            # user
            try:
                user = get_current_user()
                # validate that the user still exists
                user = get_user_model().objects.get(pk=user.pk)
            except:
                user = None

            if isinstance(user, AnonymousUser):
                user = None

            # callbacks
            kwargs[
                "request"
            ] = get_current_request()  # make request available for callbacks
            create_crud_event = all(
                callback(
                    instance,
                    object_json_repr,
                    created,
                    raw,
                    using,
                    update_fields,
                    **kwargs
                )
                for callback in CRUD_DIFFERENCE_CALLBACKS
                if callable(callback)
            )

            # create crud event only if all callbacks returned True
            if create_crud_event and created:

                def crud_flow():
                    try:
                        with transaction.atomic(using=DATABASE_ALIAS):
                            crud_event = audit_logger.crud(
                                {
                                    "event_type": event_type,
                                    "object_repr": str(instance),
                                    "object_json_repr": object_json_repr,
                                    "object_id": instance.pk,
                                    "user_id": getattr(user, "id", None),
                                    "created": timezone.now(),
                                    "user_pk_as_string": str(user.pk) if user else user,
                                }
                            )
                    except Exception as e:
                        try:
                            logger.exception(
                                "easy audit had a post_save exception on CRUDEvent creation. instance: {}, instance pk: {}".format(
                                    instance, instance.pk
                                )
                            )
                        except Exception:
                            pass

                if getattr(settings, "TEST", False):
                    crud_flow()
                else:
                    transaction.on_commit(crud_flow, using=using)
    except Exception:
        logger.exception("easy audit had a post-save exception.")