# Path: ricloud/signing.py
# class Signature:
#     """Helper for handling hmac signatures."""
# 
#     class SignatureError(Exception):
#         """Generic signature error."""
# 
#     class InvalidSignatureHeader(SignatureError):
#         """Signature header did not conform to the expected format."""
# 
#     class InvalidSignature(SignatureError):
#         """Signature did not match the expected signature given the payload and secret."""
# 
#     class InvalidSignatureTimestamp(SignatureError):
#         """Timestamp too old, not accepting signature as relevant."""
# 
#     def __init__(self, signature, timestamp):
#         self.signature = signature
#         self.timestamp = timestamp
# 
#     _header_format = "t={timestamp},s={signature}"
# 
#     def to_header(self):
#         """Dump the signature to a header format."""
#         signature = compat.want_text(encode_b64(self.signature))
# 
#         return Signature._header_format.format(
#             timestamp=self.timestamp, signature=signature
#         )
# 
#     @classmethod
#     def from_header(cls, header):
#         """Load a signature from a header string."""
#         try:
#             timestamp, signature = header.split(",", 1)
# 
#             timestamp = int(timestamp[2:])
#             signature = signature[2:]
# 
#             signature = decode_b64(compat.want_bytes(signature))
#         except Exception:
#             raise Signature.InvalidSignatureHeader
# 
#         return Signature(signature, timestamp)
# 
#     @classmethod
#     def sign(cls, data, secret):
#         """Sign a bit of data with the given secret."""
#         timestamp = compat.want_text(generate_timestamp())
# 
#         payload = cls._get_payload(data, timestamp)
# 
#         signature = hmac_sign(payload, secret)
# 
#         return Signature(signature, timestamp)
# 
#     def verify(self, data, secret, delta=None):
#         """Verify a signature is valid for a given payload and secret."""
#         payload = self._get_payload(data, self.timestamp)
# 
#         if not hmac_verify(self.signature, payload, secret):
#             raise Signature.InvalidSignature
# 
#         if delta and (generate_timestamp() - self.timestamp) > delta:
#             raise Signature.InvalidSignatureTimestamp
# 
#     @staticmethod
#     def _get_payload(data, timestamp):
#         return ".".join([compat.want_text(str(timestamp)), compat.want_text(data)])
# 
# Path: ricloud/utils.py
# def encode_json(data, indent=None):
#     return json.dumps(data, indent=indent, cls=DataEncoder, ensure_ascii=False)


from flask import Flask, request, abort
from ricloud.signing import Signature
from ricloud.utils import encode_json
@app.route("/webhooks/<uuid:event_id>", methods=["post"])
def webhooks(event_id):
    if not request.is_json:
        abort(400)

    webhook_secret = app.config.get("WEBHOOK_SECRET")
    webhook_delta = app.config.get("WEBHOOK_DELTA")

    if webhook_secret and not verify_request(
        request, webhook_secret, delta=webhook_delta
    ):
        abort(400)

    only = app.config.get("EVENTS_ONLY")
    exclude = app.config.get("EVENTS_EXCLUDE")

    try:
        handle_event(request.json, only=only, exclude=exclude)
    except Exception as exc:
        print("Exception occurred during event handling:", str(exc))
        abort(400)

    return "OK"


def verify_request(request, secret, delta=600):
    signature = Signature.from_header(request.headers["Ricloud-Signature"])

    try:
        signature.verify(request.data, secret, delta=delta)

# Path: ricloud/signing.py
# class Signature:
#     """Helper for handling hmac signatures."""
# 
#     class SignatureError(Exception):
#         """Generic signature error."""
# 
#     class InvalidSignatureHeader(SignatureError):
#         """Signature header did not conform to the expected format."""
# 
#     class InvalidSignature(SignatureError):
#         """Signature did not match the expected signature given the payload and secret."""
# 
#     class InvalidSignatureTimestamp(SignatureError):
#         """Timestamp too old, not accepting signature as relevant."""
# 
#     def __init__(self, signature, timestamp):
#         self.signature = signature
#         self.timestamp = timestamp
# 
#     _header_format = "t={timestamp},s={signature}"
# 
#     def to_header(self):
#         """Dump the signature to a header format."""
#         signature = compat.want_text(encode_b64(self.signature))
# 
#         return Signature._header_format.format(
#             timestamp=self.timestamp, signature=signature
#         )
# 
#     @classmethod
#     def from_header(cls, header):
#         """Load a signature from a header string."""
#         try:
#             timestamp, signature = header.split(",", 1)
# 
#             timestamp = int(timestamp[2:])
#             signature = signature[2:]
# 
#             signature = decode_b64(compat.want_bytes(signature))
#         except Exception:
#             raise Signature.InvalidSignatureHeader
# 
#         return Signature(signature, timestamp)
# 
#     @classmethod
#     def sign(cls, data, secret):
#         """Sign a bit of data with the given secret."""
#         timestamp = compat.want_text(generate_timestamp())
# 
#         payload = cls._get_payload(data, timestamp)
# 
#         signature = hmac_sign(payload, secret)
# 
#         return Signature(signature, timestamp)
# 
#     def verify(self, data, secret, delta=None):
#         """Verify a signature is valid for a given payload and secret."""
#         payload = self._get_payload(data, self.timestamp)
# 
#         if not hmac_verify(self.signature, payload, secret):
#             raise Signature.InvalidSignature
# 
#         if delta and (generate_timestamp() - self.timestamp) > delta:
#             raise Signature.InvalidSignatureTimestamp
# 
#     @staticmethod
#     def _get_payload(data, timestamp):
#         return ".".join([compat.want_text(str(timestamp)), compat.want_text(data)])
# 
# Path: ricloud/utils.py
# def encode_json(data, indent=None):
#     return json.dumps(data, indent=indent, cls=DataEncoder, ensure_ascii=False)


# Path: ricloud/webhooks.py
from flask import Flask, request, abort
from ricloud.signing import Signature
from ricloud.utils import encode_json

@app.route("/webhooks/<uuid:event_id>", methods=["post"])
def webhooks(event_id):
    if not request.is_json:
        abort(400)

    webhook_secret = app.config.get("WEBHOOK_SECRET")
    webhook_delta = app.config.get("WEBHOOK_DELTA")

    if webhook_secret and not verify_request(
        request, webhook_secret, delta=webhook_delta
    ):
        abort(400)

    only = app.config.get("EVENTS_ONLY")
    exclude = app.config.get("EVENTS_EXCLUDE")

    try:
        handle_event(request.json, only=only, exclude=exclude)
    except Exception as exc:
        print("Exception occurred during event handling:", str(exc))
        abort(400)

    return "OK"


def verify_request(request, secret, delta=600):
    signature = Signature.from_header(request.headers["Ricloud-Signature"])

    try:
        signature.verify(request.data, secret, delta=delta)

    except Signature.SignatureError as exc: