<commit_before>"""
Webhooks for FOIA app
"""

# Django
from django.conf import settings
from django.http.response import (
    HttpResponse,
    HttpResponseBadRequest,
    HttpResponseForbidden,
)
from django.views.decorators.csrf import csrf_exempt

# Standard Library
import hashlib
import hmac
import json
import logging
import time

# Third Party
import dateutil.parser

# MuckRock
from muckrock.communication.models import MailCommunication
from muckrock.core.utils import new_action

logger = logging.getLogger(__name__)


@csrf_exempt
def lob_webhook(request):
    """Handle Lob Webhook"""

    logger.info("Lob webhook")

    if not _validate_lob(
        request.META["HTTP_LOB_SIGNATURE"],
        request.META["HTTP_LOB_SIGNATURE_TIMESTAMP"],
        request.body,
    ):
        logger.warning("Lob webhook failed verification")
        return HttpResponseForbidden()

    try:
        data = json.loads(request.body)
    except ValueError:
        logger.error("Lob webhook JSON decode error")
        return HttpResponseBadRequest("JSON decode error")

    try:
        mail_id = data["body"]["metadata"]["mail_id"]
    except KeyError:
        logger.error("Lob webhook JSON missing data")
        return HttpResponseBadRequest("Missing JSON data")

    mail = MailCommunication.objects.filter(pk=mail_id).first()

    if mail is None:
        logger.error("Missing mail communication for mail_id: %s", mail_id)
    elif mail is not None:
        event = mail.events.create(
            datetime=dateutil.parser.parse(data["date_created"]),
            event=data["event_type"]["id"],
        )
        if (
            event.event == "check.processed_for_delivery"
            and settings.CHECK_NOTIFICATIONS
        ):
            foia = mail.communication.foia
            action = new_action(
                foia.agency, "check processed for delivery", target=foia, public=False
            )
            foia.notify(action)

    return HttpResponse("OK")


def _validate_lob(signature, timestamp, body):
    """Verify the message is from Lob"""
    digest = hmac.new(
        key=settings.LOB_WEBHOOK_KEY.encode("utf8"),
        # timestamp is a string, body is already bytes
        msg=timestamp.encode("utf8") + b"." + body,
        digestmod=hashlib.sha256,
    ).hexdigest()
    match = hmac.compare_digest(signature, digest)
    logging.info(
        "Lob webhook validate debug: "
        "signature: %s timestamp: %s digest: %s match: %s time: %s",
        signature,
        timestamp,
        digest,
        match,
        time.time(),
    )
    return match and int(timestamp) / 1000 + 300 > time.time()<commit_msg>lob webhook debug info<commit_after>"""
Webhooks for FOIA app
"""

# Django
from django.conf import settings
from django.http.response import (
    HttpResponse,
    HttpResponseBadRequest,
    HttpResponseForbidden,
)
from django.views.decorators.csrf import csrf_exempt

# Standard Library
import hashlib
import hmac
import json
import logging
import time

# Third Party
import dateutil.parser

# MuckRock
from muckrock.communication.models import MailCommunication
from muckrock.core.utils import new_action

logger = logging.getLogger(__name__)


@csrf_exempt
def lob_webhook(request):
    """Handle Lob Webhook"""

    logger.info("Lob webhook")

    if not _validate_lob(
        request.META["HTTP_LOB_SIGNATURE"],
        request.META["HTTP_LOB_SIGNATURE_TIMESTAMP"],
        request.body,
    ):
        logger.warning("Lob webhook failed verification: %s", request.META)
        return HttpResponseForbidden()

    try:
        data = json.loads(request.body)
    except ValueError:
        logger.error("Lob webhook JSON decode error")
        return HttpResponseBadRequest("JSON decode error")

    try:
        mail_id = data["body"]["metadata"]["mail_id"]
    except KeyError:
        logger.error("Lob webhook JSON missing data")
        return HttpResponseBadRequest("Missing JSON data")

    mail = MailCommunication.objects.filter(pk=mail_id).first()

    if mail is None:
        logger.error("Missing mail communication for mail_id: %s", mail_id)
    elif mail is not None:
        event = mail.events.create(
            datetime=dateutil.parser.parse(data["date_created"]),
            event=data["event_type"]["id"],
        )
        if (
            event.event == "check.processed_for_delivery"
            and settings.CHECK_NOTIFICATIONS
        ):
            foia = mail.communication.foia
            action = new_action(
                foia.agency, "check processed for delivery", target=foia, public=False
            )
            foia.notify(action)

    return HttpResponse("OK")


def _validate_lob(signature, timestamp, body):
    """Verify the message is from Lob"""
    digest = hmac.new(
        key=settings.LOB_WEBHOOK_KEY.encode("utf8"),
        # timestamp is a string, body is already bytes
        msg=timestamp.encode("utf8") + b"." + body,
        digestmod=hashlib.sha256,
    ).hexdigest()
    match = hmac.compare_digest(signature, digest)
    logger.info(
        "Lob webhook validate debug: "
        "signature: %s timestamp: %s digest: %s match: %s time: %s",
        signature,
        timestamp,
        digest,
        match,
        time.time(),
    )
    return match and int(timestamp) / 1000 + 300 > time.time()
{'fraction_non_alphanumeric': 0.10214044310927525, 'fraction_numerical': 0.004506196019526849, 'mean_word_length': 2.78069552874379, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3806998', 'n_tokens_mistral': 1580, 'n_tokens_neox': 1553, 'n_words': 388}