From f544e80b31b7b818a93f7a56e93b400489a436ff Mon Sep 17 00:00:00 2001 From: PhilipWafula Date: Wed, 21 Apr 2021 01:37:14 +0300 Subject: [PATCH] Adds scripts to handle pin imports. --- .../scripts/cic_ussd/import_pins.py | 70 +++++++++++++++ .../scripts/create_import_pins.py | 85 +++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 apps/contract-migration/scripts/cic_ussd/import_pins.py create mode 100644 apps/contract-migration/scripts/create_import_pins.py diff --git a/apps/contract-migration/scripts/cic_ussd/import_pins.py b/apps/contract-migration/scripts/cic_ussd/import_pins.py new file mode 100644 index 00000000..37bc5eb4 --- /dev/null +++ b/apps/contract-migration/scripts/cic_ussd/import_pins.py @@ -0,0 +1,70 @@ +# standard import +import argparse +import csv +import logging +import os + +# third-party imports +import celery +import confini + +# local imports +from import_task import * + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +default_config_dir = './config' + +arg_parser = argparse.ArgumentParser() +arg_parser.add_argument('-c', type=str, default=default_config_dir, help='config root to use') +arg_parser.add_argument('--env-prefix', + default=os.environ.get('CONFINI_ENV_PREFIX'), + dest='env_prefix', + type=str, + help='environment prefix for variables to overwrite configuration') +arg_parser.add_argument('-q', type=str, default='cic-import-ussd', help='celery queue to submit transaction tasks to') +arg_parser.add_argument('-v', help='be verbose', action='store_true') +arg_parser.add_argument('-vv', help='be more verbose', action='store_true') +arg_parser.add_argument('pins_dir', default='out', type=str, help='user export directory') +args = arg_parser.parse_args() + +# set log levels +if args.v: + logg.setLevel(logging.INFO) +elif args.vv: + logg.setLevel(logging.DEBUG) + +# process configs +config_dir = args.c +config = confini.Config(config_dir, os.environ.get('CONFINI_ENV_PREFIX')) +config.process() + +celery_app = celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL')) + +db_configs = { + 'database': config.get('DATABASE_NAME'), + 'host': config.get('DATABASE_HOST'), + 'port': config.get('DATABASE_PORT'), + 'user': config.get('DATABASE_USER'), + 'password': config.get('DATABASE_PASSWORD') +} + + +def main(): + with open(f'{args.pins_dir}/pins.csv') as pins_file: + phone_to_pins = [tuple(row) for row in csv.reader(pins_file)] + + s_import_pins = celery.signature( + 'import_task.set_pins', + (db_configs, phone_to_pins), + queue=args.q + ) + s_import_pins.apply_async() + + argv = ['worker', '-Q', 'cic-import-ussd', '--loglevel=DEBUG'] + celery_app.worker_main(argv) + + +if __name__ == '__main__': + main() diff --git a/apps/contract-migration/scripts/create_import_pins.py b/apps/contract-migration/scripts/create_import_pins.py new file mode 100644 index 00000000..ae274505 --- /dev/null +++ b/apps/contract-migration/scripts/create_import_pins.py @@ -0,0 +1,85 @@ +# standard imports +import argparse +import json +import logging +import os + +# third-party imports +import bcrypt +import celery +import confini +import phonenumbers +import random +from cic_types.models.person import Person +from cryptography.fernet import Fernet + +# local imports + + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +script_dir = os.path.realpath(os.path.dirname(__file__)) +default_config_dir = os.environ.get('CONFINI_DIR', os.path.join(script_dir, 'config')) + +arg_parser = argparse.ArgumentParser() +arg_parser.add_argument('-c', type=str, default=default_config_dir, help='Config dir') +arg_parser.add_argument('-v', action='store_true', help='Be verbose') +arg_parser.add_argument('-vv', action='store_true', help='Be more verbose') +arg_parser.add_argument('--userdir', type=str, help='path to users export dir tree') +arg_parser.add_argument('pins_dir', type=str, help='path to pin export dir tree') + + +args = arg_parser.parse_args() + +if args.v: + logg.setLevel(logging.INFO) +elif args.vv: + logg.setLevel(logging.DEBUG) + +config = confini.Config(args.c, os.environ.get('CONFINI_ENV_PREFIX')) +config.process() +logg.info('loaded config\n{}'.format(config)) + +celery_app = celery.Celery(broker=config.get('CELERY_BROKER_URL'), backend=config.get('CELERY_RESULT_URL')) + +user_dir = args.userdir +pins_dir = args.pins_dir + + +def generate_password_hash(): + key = Fernet.generate_key() + fnt = Fernet(key) + pin = str(random.randint(1000, 9999)) + return fnt.encrypt(bcrypt.hashpw(pin.encode('utf-8'), bcrypt.gensalt())).decode() + + +user_old_dir = os.path.join(user_dir, 'old') +logg.debug(f'reading user data from: {user_old_dir}') + +pins_file = open(f'{pins_dir}/pins.csv', 'w') + +if __name__ == '__main__': + + for x in os.walk(user_old_dir): + for y in x[2]: + if y[len(y) - 5:] != '.json': + continue + filepath = os.path.join(x[0], y) + f = open(filepath, 'r') + try: + o = json.load(f) + except json.decoder.JSONDecodeError as e: + f.close() + logg.error('load error for {}: {}'.format(y, e)) + continue + f.close() + u = Person.deserialize(o) + + phone_object = phonenumbers.parse(u.tel) + phone = phonenumbers.format_number(phone_object, phonenumbers.PhoneNumberFormat.E164) + password_hash = generate_password_hash() + pins_file.write(f'{phone},{password_hash}\n') + logg.debug(f'Writing phone: {phone}, password_hash: {password_hash}') + + pins_file.close() \ No newline at end of file