2022-06-16 10:12:37 +09:00
|
|
|
# SPDX-FileCopyrightText: 2022 n9k <https://git.076.ne.jp/ninya9k>
|
2022-03-07 23:51:59 +09:00
|
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
|
2022-02-20 13:23:32 +09:00
|
|
|
import secrets
|
|
|
|
|
|
|
|
from quart import current_app
|
|
|
|
|
|
|
|
from anonstream.helpers.captcha import generate_captcha_digest, generate_captcha_image
|
|
|
|
|
|
|
|
CONFIG = current_app.config
|
2022-02-20 18:15:10 +09:00
|
|
|
CAPTCHAS = current_app.captchas
|
2022-02-20 13:23:32 +09:00
|
|
|
CAPTCHA_FACTORY = current_app.captcha_factory
|
|
|
|
CAPTCHA_SIGNER = current_app.captcha_signer
|
|
|
|
|
|
|
|
def generate_random_captcha_solution():
|
|
|
|
return ''.join(
|
|
|
|
secrets.choice(CONFIG['CAPTCHA_ALPHABET'])
|
|
|
|
for _ in range(CONFIG['CAPTCHA_LENGTH'])
|
|
|
|
)
|
|
|
|
|
|
|
|
def _get_random_cached_captcha_digest():
|
|
|
|
chosen_index = secrets.randbelow(len(CAPTCHAS))
|
|
|
|
for index, digest in enumerate(CAPTCHAS):
|
|
|
|
if index == chosen_index:
|
|
|
|
break
|
|
|
|
return digest
|
|
|
|
|
|
|
|
def get_random_captcha_digest():
|
|
|
|
if len(CAPTCHAS) >= CONFIG['MAX_CAPTCHAS']:
|
|
|
|
digest = _get_random_cached_captcha_digest()
|
|
|
|
else:
|
|
|
|
salt = secrets.token_bytes(16)
|
|
|
|
solution = generate_random_captcha_solution()
|
|
|
|
digest = generate_captcha_digest(CAPTCHA_SIGNER, salt, solution)
|
|
|
|
CAPTCHAS[digest] = {'solution': solution}
|
|
|
|
|
|
|
|
return digest
|
|
|
|
|
2022-02-21 07:07:32 +09:00
|
|
|
def get_random_captcha_digest_for(user):
|
|
|
|
if user['verified']:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
return get_random_captcha_digest()
|
|
|
|
|
2022-02-20 13:23:32 +09:00
|
|
|
def get_captcha_image(digest):
|
|
|
|
try:
|
|
|
|
captcha = CAPTCHAS[digest]
|
|
|
|
except KeyError:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
if 'image' not in captcha:
|
|
|
|
captcha['image'] = generate_captcha_image(
|
|
|
|
factory=CAPTCHA_FACTORY,
|
|
|
|
solution=captcha.pop('solution'),
|
|
|
|
)
|
|
|
|
return captcha['image']
|