69 lines
2.8 KiB
Python
69 lines
2.8 KiB
Python
from src.application.abstractions import IUnitOfWork
|
|
from src.application.contracts import IHashService, ILogger, ICache
|
|
from src.application.domain.entities import UserEntity
|
|
from src.application.domain.exceptions import BadRequestException, ConflictException
|
|
from src.infrastructure.database.decorators import transactional
|
|
|
|
|
|
class SetEncryptedMnemonicCompleteCommand:
|
|
def __init__(
|
|
self,
|
|
unit_of_work: IUnitOfWork,
|
|
hash_service: IHashService,
|
|
cache: ICache,
|
|
logger: ILogger,
|
|
):
|
|
self._unit_of_work = unit_of_work
|
|
self._hash_service = hash_service
|
|
self._cache = cache
|
|
self._logger = logger
|
|
|
|
@transactional
|
|
async def __call__(self, *, user_id: str, code: str, encrypted_mnemonic: str) -> UserEntity:
|
|
code = (code or '').strip()
|
|
|
|
USER_PREFIX = 'encrypted_mnemonic:user:'
|
|
CODE_PREFIX = 'encrypted_mnemonic:code:'
|
|
|
|
user_key = f'{USER_PREFIX}{user_id}'
|
|
code_key = f'{CODE_PREFIX}{code}'
|
|
|
|
user = await self._unit_of_work.user_repository.get_user_by_id(user_id=user_id)
|
|
if user.encrypted_mnemonic is not None:
|
|
self._logger.info(f'Encrypted mnemonic already set for user_id={user_id}')
|
|
raise ConflictException(message='Encrypted mnemonic already set and cannot be changed')
|
|
|
|
cached_user_id = await self._cache.get(code_key)
|
|
if not cached_user_id:
|
|
self._logger.info(f'Encrypted mnemonic set failed: code not found (user_id={user_id})')
|
|
raise BadRequestException(message='Invalid or expired code')
|
|
|
|
if cached_user_id != user_id:
|
|
self._logger.info(f'Encrypted mnemonic set failed: code-user mismatch (user_id={user_id})')
|
|
raise BadRequestException(message='Invalid or expired code')
|
|
|
|
code_hash = await self._cache.get(user_key)
|
|
if not code_hash:
|
|
self._logger.info(f'Encrypted mnemonic set failed: user key missing (user_id={user_id})')
|
|
raise BadRequestException(message='Invalid or expired code')
|
|
|
|
ok = await self._hash_service.verify(hashed_value=code_hash, plain_value=code)
|
|
if not ok:
|
|
self._logger.info(f'Encrypted mnemonic set failed: code hash mismatch (user_id={user_id})')
|
|
raise BadRequestException(message='Invalid or expired code')
|
|
|
|
user = await self._unit_of_work.user_repository.set_encrypted_mnemonic(
|
|
user_id=user_id,
|
|
encrypted_mnemonic=encrypted_mnemonic,
|
|
)
|
|
await self._cache.set_user(user_id, user)
|
|
|
|
try:
|
|
await self._cache.delete(code_key)
|
|
await self._cache.delete(user_key)
|
|
except Exception as e:
|
|
self._logger.warning(f'Encrypted mnemonic set cleanup failed (user_id={user_id}): {e}')
|
|
|
|
self._logger.info(f'Encrypted mnemonic set for user_id={user_id}')
|
|
return user
|