Skip to content

Instantly share code, notes, and snippets.

@UFO-101
Last active May 23, 2022 20:37
Show Gist options
  • Save UFO-101/ff5eb023eebd4d9347bd2f1e1326f14a to your computer and use it in GitHub Desktop.
Save UFO-101/ff5eb023eebd4d9347bd2f1e1326f14a to your computer and use it in GitHub Desktop.
Hypnogram.xyz Payment Intention Request Validation
import time
from flask import jsonify
from src.shared.aws_rds import rds_execute_sql as rds
from src.shared.constants import PAYMENT_RATE_LIMIT, PAYMENT_RATE_INTERVAL
from src.shared.utils import LimitedSizeDict
create_payment_rates = LimitedSizeDict(1000)
block_accounts_cache = LimitedSizeDict(1000)
def validate_payment_request_and_get_info(request, user, rate_limit=True):
# If a user makes PAYMENT_RATE_LIMIT rate_limit[ed] requests in PAYMENT_RATE_INTERVAL seconds, we block the account
rate = create_payment_rates.get(user, {}).get('rate', 0) + (1 if rate_limit else 0)
interval_start = create_payment_rates.get(user, {}).get('interval_start', 0)
rate_interval_active = interval_start > time.time() - PAYMENT_RATE_INTERVAL
if rate_limited := rate >= PAYMENT_RATE_LIMIT and rate_interval_active:
if not block_accounts_cache.get(user, {}).get('block', False):
rds(f"UPDATE users SET blocked = true WHERE id = '{user}';")
create_payment_rates[user] = {
'interval_start': interval_start if rate_interval_active else time.time(),
'rate': rate if rate_interval_active else 1
}
# Check if user blocked. Only cache for 1 min - if user is blocked by another server, cache entry won't be updated.
try:
if rate_limited or block_accounts_cache.get(user, {}).get('timestamp', 0) < time.time() - 60:
block_accounts_cache[user] = {
'timestamp': time.time(),
'block': rds(f"SELECT blocked FROM users WHERE id = '{user}';")['records'][0][0]['booleanValue']
}
except Exception as e:
return jsonify(
error_code="DB_ERROR",
error_message=str(e),
)
if rate_limited or block_accounts_cache[user]['block']: # rate_limited check should be redundant
return jsonify(
error_code="ACCOUNT_BLOCKED",
error_message="Your account has been blocked."
)
json_data = request.get_json(force=True)
if 'credits' not in json_data:
return jsonify(
error_code="MISSING_INPUT",
error_message="The number of credits to buy wasn't specified.",
)
credits_to_buy = json_data['credits']
if not isinstance(credits_to_buy, int):
return jsonify(
error_code="INVALID_INPUT",
error_message="The number of credits to buy must be an integer.",
)
price_in_cents = credit_price_in_cents(credits_to_buy)
if price_in_cents < 100:
return jsonify(
error_code="INVALID_PAYMENT_REQUEST",
error_message="Transaction amount must be at least $1.",
)
return credits_to_buy, price_in_cents
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment