Last active
May 23, 2022 20:37
-
-
Save UFO-101/ff5eb023eebd4d9347bd2f1e1326f14a to your computer and use it in GitHub Desktop.
Hypnogram.xyz Payment Intention Request Validation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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