Exemple #1
0
def pre_save_signal(sender, instance, **kwargs) -> None:
    if not settings.AUDIT_LOG_ENABLED:
        return

    if not AuditLogMiddleware.is_request():
        logger.debug("Not a request")
        return

    model_name = get_model_name(instance)
    if exclude_model(model_name):
        logger.debug(f"{model_name} ignored as per settings")
        return

    get_or_create_meta(instance)
    instance._meta.dal.event = None

    operation = Operation.UPDATE
    try:
        pre = sender.objects.get(pk=instance.pk)
    except ObjectDoesNotExist:
        # __dict__ is used on pre, therefore we need to create a function
        # that uses __dict__ too, but returns nothing.

        pre = lambda _: None
        operation = Operation.INSERT

    changes = {}

    if operation not in {Operation.INSERT, Operation.DELETE}:
        old, new = remove_non_member_fields(pre.__dict__), remove_non_member_fields(instance.__dict__)

        try:
            changes = dict(set(new.items()).difference(old.items()))
        except TypeError:  # handle non-hashable types
            old_hashable, old_non_hashable = seperate_hashable_dict(old)
            new_hashable, new_non_hashable = seperate_hashable_dict(new)

            changes = dict(set(new_hashable.items()).difference(old_hashable.items()))
            changes.update({k: v for k, v in new_non_hashable.items() if v != old_non_hashable.get(k)})

        excluded_fields = settings.AUDIT_LOG["models"]["exclude"]["fields"].get(model_name, [])
        for field in excluded_fields:
            if field in changes:
                changes[field] = "xxx"

        if not changes:
            logger.debug("No changes for model. Ignoring.")
            return

    current_user = AuditLogMiddleware.get_current_user()

    instance._meta.dal.event = Event(model=model_name, actor=current_user, entity_id=instance.pk, changes=changes)
Exemple #2
0
def post_delete_signal(sender, instance, **kwargs) -> None:
    if not settings.AUDIT_LOG_ENABLED:
        return

    if not AuditLogMiddleware.is_request():
        logger.debug("Not a request")
        return

    model_name = get_model_name(instance)
    if exclude_model(model_name):
        logger.debug(f"Ignoring {model_name}.")
        return

    event = instance._meta.dal.event
    _post_processor(instance, event, Operation.DELETE)
Exemple #3
0
def post_save_signal(sender, instance, created, update_fields: frozenset, **kwargs):
    if not settings.AUDIT_LOG_ENABLED:
        return

    if not AuditLogMiddleware.is_request():
        logger.debug("Not a request")
        return

    model_name = get_model_name(instance)
    if exclude_model(model_name):
        logger.debug(f"Ignoring {model_name}.")
        return

    operation = Operation.INSERT if created else Operation.UPDATE
    get_or_create_meta(instance)

    event = instance._meta.dal.event
    _post_processor(instance, event, operation)
Exemple #4
0
def _post_processor(instance, event: Optional[Event], operation: Operation):
    request_id = AuditLogMiddleware.get_current_request_id()
    actor = AuditLogMiddleware.get_current_user()
    model_name = get_model_name(instance)

    if not event and operation != Operation.DELETE:
        logger.debug(f"Event not received for {operation}. Ignoring.")
        return

    try:
        changes = json.dumps(event.changes if event else dict(),
                             cls=LogJsonEncoder)
    except Exception:
        logger.warning(f"Failed to log {event}", exc_info=True)
        return

    logger.info(
        f"AUDIT_LOG::{request_id}|{actor}|{operation.value}|{model_name}|ID:{instance.pk}|{changes}"
    )