Compare commits

...

3 Commits

Author SHA1 Message Date
nolash
4667916d80 Catch bogus transfers where token address is no contract 2021-05-12 08:48:50 +02:00
1f668384cc Merge branch 'philip/fix-africastalking-parser' into 'master'
Philip/fix africastalking parser

Closes cic-ussd#41

See merge request grassrootseconomics/cic-internal-integration!140
2021-05-11 10:58:00 +00:00
123dc55687 Philip/fix africastalking parser 2021-05-11 10:58:00 +00:00
8 changed files with 57 additions and 35 deletions

View File

@@ -3,7 +3,10 @@ import logging
# external imports
import celery
from cic_eth_registry.error import UnknownContractError
from cic_eth_registry.error import (
UnknownContractError,
NotAContractError,
)
from chainlib.status import Status as TxStatus
from chainlib.eth.address import to_checksum_address
from chainlib.eth.error import RequestMismatchException
@@ -124,8 +127,7 @@ class CallbackFilter(SyncFilter):
(transfer_type, transfer_data) = parser(tx, conn)
if transfer_type == None:
continue
else:
pass
break
except RequestMismatchException:
continue
@@ -168,7 +170,9 @@ class CallbackFilter(SyncFilter):
t = self.call_back(transfer_type, result)
logg.info('callback success task id {} tx {} queue {}'.format(t, tx.hash, t.queue))
except UnknownContractError:
logg.debug('callback filter {}:{} skipping "transfer" method on unknown contract {} tx {}'.format(tx.queue, tx.method, transfer_data['to'], tx.hash))
logg.debug('callback filter {}:{} skipping "transfer" method on unknown contract {} tx {}'.format(self.queue, self.method, transfer_data['to'], tx.hash))
except NotAContractError:
logg.debug('callback filter {}:{} skipping "transfer" on non-contract address {} tx {}'.format(self.queue, self.method, transfer_data['to'], tx.hash))
def __str__(self):

View File

@@ -4,7 +4,7 @@ LOCALE_FALLBACK=en
LOCALE_PATH=/usr/src/cic-ussd/var/lib/locale/
MAX_BODY_LENGTH=1024
PASSWORD_PEPPER=QYbzKff6NhiQzY3ygl2BkiKOpER8RE/Upqs/5aZWW+I=
SERVICE_CODE=*483*46#
SERVICE_CODE=*483*46#,*483*061#,*384*96#
[phone_number]
REGION=KE

View File

@@ -13,7 +13,7 @@ import argparse
import logging
import urllib
from xdg.BaseDirectory import xdg_config_home
from urllib import request
from urllib import parse, request
# third-party imports
from confini import Config
@@ -92,9 +92,9 @@ def main():
data['text'] = user_input
req = urllib.request.Request(url)
data_str = json.dumps(data)
data_bytes = data_str.encode('utf-8')
req.add_header('Content-Type', 'application/json')
urlencoded_data = parse.urlencode(data)
data_bytes = urlencoded_data.encode('utf-8')
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
req.data = data_bytes
response = urllib.request.urlopen(req)
response_data = response.read().decode('utf-8')

View File

@@ -4,6 +4,7 @@
# standard imports
import json
import logging
from urllib.parse import parse_qs
# third-party imports
import celery
@@ -33,8 +34,7 @@ from cic_ussd.requests import (get_request_endpoint,
from cic_ussd.runnable.server_base import exportable_parser, logg
from cic_ussd.session.ussd_session import UssdSession as InMemoryUssdSession
from cic_ussd.state_machine import UssdStateMachine
from cic_ussd.validator import check_ip, check_request_content_length, check_service_code, validate_phone_number, \
validate_presence
from cic_ussd.validator import check_ip, check_request_content_length, validate_phone_number, validate_presence
args = exportable_parser.parse_args()
@@ -124,6 +124,9 @@ else:
raise InitializationError(f'Default token data for: {chain_str} not found.')
valid_service_codes = config.get('APP_SERVICE_CODE').split(",")
def application(env, start_response):
"""Loads python code for application to be accessible over web server
:param env: Object containing server and request information
@@ -139,13 +142,27 @@ def application(env, start_response):
if get_request_method(env=env) == 'POST' and get_request_endpoint(env=env) == '/':
# get post data
post_data = json.load(env.get('wsgi.input'))
if env.get('CONTENT_TYPE') != 'application/x-www-form-urlencoded':
start_response('405 Play by the rules', errors_headers)
return []
service_code = post_data.get('serviceCode')
phone_number = post_data.get('phoneNumber')
external_session_id = post_data.get('sessionId')
user_input = post_data.get('text')
post_data = env.get('wsgi.input').read()
post_data = post_data.decode('utf-8')
try:
post_data = parse_qs(post_data)
except TypeError:
start_response('400 Size matters', errors_headers)
return []
service_code = post_data.get('serviceCode')[0]
phone_number = post_data.get('phoneNumber')[0]
external_session_id = post_data.get('sessionId')[0]
try:
user_input = post_data.get('text')[0]
except TypeError:
user_input = ""
# add validation for phone number
if phone_number:
@@ -162,14 +179,14 @@ def application(env, start_response):
return []
# validate service code
if not check_service_code(code=service_code, config=config):
if service_code not in valid_service_codes:
response = define_multilingual_responses(
key='ussd.kenya.invalid_service_code',
locales=['en', 'sw'],
prefix='END',
valid_service_code=config.get('APP_SERVICE_CODE'))
response_bytes, headers = define_response_with_content(headers=errors_headers, response=response)
start_response('400 Invalid service code', headers)
valid_service_code=valid_service_codes[0])
response_bytes, headers = define_response_with_content(headers=headers, response=response)
start_response('200 OK', headers)
return [response_bytes]
# validate phone number
@@ -192,3 +209,8 @@ def application(env, start_response):
start_response('200 OK,', headers)
SessionBase.session.close()
return [response_bytes]
else:
start_response('405 Play by the rules', errors_headers)
return []

View File

@@ -45,19 +45,6 @@ def check_request_content_length(config: Config, env: dict):
config.get('APP_MAX_BODY_LENGTH'))
def check_service_code(code: str, config: Config):
"""Checks whether provided code matches expected service code
:param config: A dictionary object containing configuration values
:type config: Config
:param code: Service code passed over request
:type code: str
:return: Service code validity
:rtype: boolean
"""
return code == config.get('APP_SERVICE_CODE')
def check_known_user(phone: str):
"""
This method attempts to ascertain whether the user already exists and is known to the system.

View File

@@ -158,6 +158,8 @@ en:
Your Sarafu-Network balances is: %{token_balance}
00. Back
99. Exit
invalid_service_code: |-
Please dial %{valid_service_code} to access Sarafu Network
help: |-
CON For assistance call %{support_phone}
00. Back

View File

@@ -158,6 +158,8 @@ sw:
Akaunti yako ya Sarafu-Network ina salio ifuatayo: %{token_balance}
00. Nyuma
99. Ondoka
invalid_service_code: |-
Bonyeza %{valid_service_code} kutumia mtandao wa Sarafu
help: |-
CON Kwa usaidizi piga simu %{support_phone}
0. Nyuma

View File

@@ -33,6 +33,7 @@ from chainlib.eth.tx import TxFactory
from chainlib.jsonrpc import jsonrpc_template
from chainlib.eth.error import EthException
from chainlib.chain import ChainSpec
from chainlib.eth.constant import ZERO_ADDRESS
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
from crypto_dev_signer.keystore.dict import DictKeystore
from cic_types.models.person import Person
@@ -51,7 +52,7 @@ argparser.add_argument('-c', type=str, default=config_dir, help='config root to
argparser.add_argument('--old-chain-spec', type=str, dest='old_chain_spec', default='evm:oldchain:1', help='chain spec')
argparser.add_argument('-i', '--chain-spec', type=str, dest='i', help='chain spec')
argparser.add_argument('-r', '--registry-address', type=str, dest='r', help='CIC Registry address')
argparser.add_argument('--token-symbol', default='SRF', type=str, dest='token_symbol', help='Token symbol to use for trnsactions')
argparser.add_argument('--token-symbol', default='GFT', type=str, dest='token_symbol', help='Token symbol to use for trnsactions')
argparser.add_argument('--head', action='store_true', help='start at current block height (overrides --offset)')
argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration')
argparser.add_argument('-q', type=str, default='cic-eth', help='celery queue to submit transaction tasks to')
@@ -252,6 +253,10 @@ def main():
except ValueError as e:
logg.critical('lookup failed for token {}: {}'.format(token_symbol, e))
sys.exit(1)
if sarafu_token_address == ZERO_ADDRESS:
raise KeyError('token address for symbol {} is zero'.format(token_symbol))
logg.info('found token address {}'.format(sarafu_token_address))
syncer_backend = MemBackend(chain_str, 0)