diff --git a/apps/cic-ussd/.config/app.ini b/apps/cic-ussd/.config/app.ini index 9d7cd2c0..95a36052 100644 --- a/apps/cic-ussd/.config/app.ini +++ b/apps/cic-ussd/.config/app.ini @@ -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 diff --git a/apps/cic-ussd/cic_ussd/runnable/client.py b/apps/cic-ussd/cic_ussd/runnable/client.py index f6fc050b..5ea98e8e 100644 --- a/apps/cic-ussd/cic_ussd/runnable/client.py +++ b/apps/cic-ussd/cic_ussd/runnable/client.py @@ -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') diff --git a/apps/cic-ussd/cic_ussd/runnable/daemons/cic_user_ussd_server.py b/apps/cic-ussd/cic_ussd/runnable/daemons/cic_user_ussd_server.py index f867dffe..92c4147f 100644 --- a/apps/cic-ussd/cic_ussd/runnable/daemons/cic_user_ussd_server.py +++ b/apps/cic-ussd/cic_ussd/runnable/daemons/cic_user_ussd_server.py @@ -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 [] + diff --git a/apps/cic-ussd/cic_ussd/validator.py b/apps/cic-ussd/cic_ussd/validator.py index 89896955..660f2783 100644 --- a/apps/cic-ussd/cic_ussd/validator.py +++ b/apps/cic-ussd/cic_ussd/validator.py @@ -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. diff --git a/apps/cic-ussd/var/lib/locale/ussd.en.yml b/apps/cic-ussd/var/lib/locale/ussd.en.yml index e0751543..8cd16b9b 100644 --- a/apps/cic-ussd/var/lib/locale/ussd.en.yml +++ b/apps/cic-ussd/var/lib/locale/ussd.en.yml @@ -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 diff --git a/apps/cic-ussd/var/lib/locale/ussd.sw.yml b/apps/cic-ussd/var/lib/locale/ussd.sw.yml index 123363be..7718f477 100644 --- a/apps/cic-ussd/var/lib/locale/ussd.sw.yml +++ b/apps/cic-ussd/var/lib/locale/ussd.sw.yml @@ -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