# standard imports import json import logging import re from urllib.parse import quote_plus # external imports from sqlalchemy import desc from sqlalchemy.orm.session import Session # local imports from cic_ussd.db.enum import AccountStatus from cic_ussd.db.models.account import Account from cic_ussd.db.models.base import SessionBase from cic_ussd.http.requests import get_query_parameters, get_request_method from cic_ussd.http.responses import with_content_headers logg = logging.getLogger(__file__) def _get_locked_accounts(env: dict, session: Session): offset = 0 limit = 100 locked_accounts_path = r'/accounts/locked/(\d+)?/?(\d+)?' r = re.match(locked_accounts_path, env.get('PATH_INFO')) if r: if r.lastindex > 1: offset = r[1] limit = r[2] else: limit = r[1] session = SessionBase.bind_session(session) accounts = session.query(Account.blockchain_address)\ .filter(Account.status == AccountStatus.LOCKED.value, Account.failed_pin_attempts >= 3)\ .order_by(desc(Account.updated))\ .offset(offset)\ .limit(limit)\ .all() accounts = [blockchain_address for (blockchain_address,) in accounts] SessionBase.release_session(session=session) response = json.dumps(accounts) return response, '200 OK' def locked_accounts(env: dict, session: Session) -> tuple: """ :param env: :type env: :param session: :type session: :return: :rtype: """ if get_request_method(env) == 'GET': return _get_locked_accounts(env, session) return '', '405 Play by the rules' def pin_reset(env: dict, phone_number: str, session: Session): """""" account = session.query(Account).filter_by(phone_number=phone_number).first() if not account: return '', '404 Not found' if get_request_method(env) == 'PUT': return account.reset_pin(session), '200 OK' if get_request_method(env) == 'GET': status = account.get_status(session) response = { 'status': f'{status}' } response = json.dumps(response) return response, '200 OK' def handle_pin_requests(env, session, errors_headers, start_response): phone_number = get_query_parameters(env=env, query_name='phoneNumber') phone_number = quote_plus(phone_number) response, message = pin_reset(env=env, phone_number=phone_number, session=session) response_bytes, headers = with_content_headers(errors_headers, response) session.commit() session.close() start_response(message, headers) return [response_bytes]