mirror of
https://github.com/simple-login/app.git
synced 2024-11-16 17:08:30 +01:00
35f6e67053
* feat: set up UserAuditLog * refactor: extract payment callbacks into their own files + handle subscription user_audit_log * feat: handle account linking for user audit log * chore: user_audit_log for mailboxes * chore: user_audit_log for custom domains * chore: user_audit_log for contacts * chore: user_audit_log for directories * fix: do not enforce cronjob being defined in choices + enable user deletion * chore: user_audit_log for user deletion * refactor: change emit_user_audit_log function to receive the full user object * feat: add user_audit_log migration * test: fix tests * test: add some tests for user_audit_log * fix: spf record verification user_audit_log * chore: add missing index to user_audit_log.created_at * chore: add missing index to alias_audit_log.created_at
121 lines
4 KiB
Python
121 lines
4 KiB
Python
from typing import Optional
|
|
|
|
import arrow
|
|
|
|
from coinbase_commerce.error import WebhookInvalidPayload, SignatureVerificationError
|
|
from coinbase_commerce.webhook import Webhook
|
|
from flask import Flask, request
|
|
|
|
from app.config import COINBASE_WEBHOOK_SECRET
|
|
from app.db import Session
|
|
from app.email_utils import send_email, render
|
|
from app.log import LOG
|
|
from app.models import CoinbaseSubscription, User
|
|
from app.subscription_webhook import execute_subscription_webhook
|
|
from app.user_audit_log_utils import emit_user_audit_log, UserAuditLogAction
|
|
|
|
|
|
def setup_coinbase_commerce(app: Flask):
|
|
@app.route("/coinbase", methods=["POST"])
|
|
def coinbase_webhook():
|
|
# event payload
|
|
request_data = request.data.decode("utf-8")
|
|
# webhook signature
|
|
request_sig = request.headers.get("X-CC-Webhook-Signature", None)
|
|
|
|
try:
|
|
# signature verification and event object construction
|
|
event = Webhook.construct_event(
|
|
request_data, request_sig, COINBASE_WEBHOOK_SECRET
|
|
)
|
|
except (WebhookInvalidPayload, SignatureVerificationError) as e:
|
|
LOG.e("Invalid Coinbase webhook")
|
|
return str(e), 400
|
|
|
|
LOG.d("Coinbase event %s", event)
|
|
|
|
if event["type"] == "charge:confirmed":
|
|
if handle_coinbase_event(event):
|
|
return "success", 200
|
|
else:
|
|
return "error", 400
|
|
|
|
return "success", 200
|
|
|
|
|
|
def handle_coinbase_event(event) -> bool:
|
|
server_user_id = event["data"]["metadata"]["user_id"]
|
|
try:
|
|
user_id = int(server_user_id)
|
|
except ValueError:
|
|
user_id = int(float(server_user_id))
|
|
|
|
code = event["data"]["code"]
|
|
user: Optional[User] = User.get(user_id)
|
|
if not user:
|
|
LOG.e("User not found %s", user_id)
|
|
return False
|
|
|
|
coinbase_subscription: CoinbaseSubscription = CoinbaseSubscription.get_by(
|
|
user_id=user_id
|
|
)
|
|
|
|
if not coinbase_subscription:
|
|
LOG.d("Create a coinbase subscription for %s", user)
|
|
coinbase_subscription = CoinbaseSubscription.create(
|
|
user_id=user_id, end_at=arrow.now().shift(years=1), code=code, commit=True
|
|
)
|
|
emit_user_audit_log(
|
|
user=user,
|
|
action=UserAuditLogAction.Upgrade,
|
|
message="Upgraded though Coinbase",
|
|
commit=True,
|
|
)
|
|
send_email(
|
|
user.email,
|
|
"Your SimpleLogin account has been upgraded",
|
|
render(
|
|
"transactional/coinbase/new-subscription.txt",
|
|
user=user,
|
|
coinbase_subscription=coinbase_subscription,
|
|
),
|
|
render(
|
|
"transactional/coinbase/new-subscription.html",
|
|
user=user,
|
|
coinbase_subscription=coinbase_subscription,
|
|
),
|
|
)
|
|
else:
|
|
if coinbase_subscription.code != code:
|
|
LOG.d("Update code from %s to %s", coinbase_subscription.code, code)
|
|
coinbase_subscription.code = code
|
|
|
|
if coinbase_subscription.is_active():
|
|
coinbase_subscription.end_at = coinbase_subscription.end_at.shift(years=1)
|
|
else: # already expired subscription
|
|
coinbase_subscription.end_at = arrow.now().shift(years=1)
|
|
|
|
emit_user_audit_log(
|
|
user=user,
|
|
action=UserAuditLogAction.SubscriptionExtended,
|
|
message="Extended coinbase subscription",
|
|
)
|
|
Session.commit()
|
|
|
|
send_email(
|
|
user.email,
|
|
"Your SimpleLogin account has been extended",
|
|
render(
|
|
"transactional/coinbase/extend-subscription.txt",
|
|
user=user,
|
|
coinbase_subscription=coinbase_subscription,
|
|
),
|
|
render(
|
|
"transactional/coinbase/extend-subscription.html",
|
|
user=user,
|
|
coinbase_subscription=coinbase_subscription,
|
|
),
|
|
)
|
|
execute_subscription_webhook(user)
|
|
|
|
return True
|