def update_borrower(borrower, idx, borrowers, deed_token): borrower_service = BorrowerService() borrower_json = { "id": "", "token": "", "forename": borrower['forename'], "surname": borrower['surname'] } if 'middle_name' in borrower: borrower_json["middle_name"] = borrower["middle_name"] if 'id' not in borrower: created_borrower = borrower_service.saveBorrower(borrower, deed_token) borrower_json["id"] = created_borrower.id borrower_json["token"] = created_borrower.token else: borrower_updater = BorrowerModel() updated_borrower = borrower_updater.update_borrower_by_id(borrower) borrower_json["id"] = int(borrower["id"]) borrower_json["token"] = updated_borrower.token return borrower_json
def test_update_borrower_by_id_no_borrower(self, mock_db, mock_query): updated_borrower = copy.deepcopy( DeedHelper._valid_single_borrower_update) mock_query.return_value = None borrower = Borrower() res = borrower.update_borrower_by_id(updated_borrower) self.assertEqual(res, "Error No Borrower")
def delete_orphaned_borrowers(deed): borrower_list = [] for borrower in deed.deed["borrowers"]: borrower_list.append(borrower["id"]) borrower_model_delete = BorrowerModel() borrower_model_delete.delete_borrowers_not_on_deed(borrower_list, deed.token) return True
def delete_borrower(borrower_id): borrower = None borrowerModel = Borrower() try: borrower = borrowerModel.delete(borrower_id) except Exception as inst: application.app.logger.error(str(type(inst)) + ":" + str(inst)) if borrower is None: abort(status.HTTP_404_NOT_FOUND) else: return jsonify({"id": borrower_id}), status.HTTP_200_OK
def delete_borrower(borrower_id): borrower = None borrowerModel = Borrower() try: borrower = borrowerModel.delete(borrower_id) except Exception as inst: LOGGER.error(str(type(inst)) + ":" + str(inst)) if borrower is None: abort(status.HTTP_404_NOT_FOUND) else: return jsonify({"id": borrower_id}), status.HTTP_200_OK
def test_update_borrower_by_id(self, mock_db, mock_query): updated_borrower = copy.deepcopy( DeedHelper._valid_single_borrower_update) testBorrower = borrower_object_helper(updated_borrower) mock_query.return_value = testBorrower updated_borrower["forename"] = "Frank" borrower = Borrower() res = borrower.update_borrower_by_id(updated_borrower) self.assertEqual(res.forename, "Frank")
def issue_sms(deed_reference, borrower_token): deed_instance = Deed() deed = deed_instance.get_deed(deed_reference) esec_client = make_esec_client() if deed is None: application.app.logger.error( "Database Exception 404 for deed reference - %s" % deed_reference) abort(status.HTTP_404_NOT_FOUND) else: application.app.logger.info( "Signing deed for borrower_token %s against deed reference %s" % (borrower_token, deed_reference)) try: application.app.logger.info("getting existing XML") borrower = Borrower.get_by_token(borrower_token) if not borrower.esec_user_name: application.app.logger.info( "creating esec user for borrower[token:%s]", borrower.token) forenames = ' '.join( filter(bool, (borrower.forename, borrower.middlename))) user_id, status_code = esec_client.issue_sms( forenames, borrower.surname, deed.organisation_name, borrower.phonenumber) if status_code == 200: application.app.logger.info( "Created new esec user: %s for borrower[token:%s]", str(user_id.decode()), borrower.token) borrower.esec_user_name = user_id.decode() borrower.save() else: application.app.logger.error( "Unable to create new e-sec user for borrower [token:%s]", borrower.token) abort(status.HTTP_500_INTERNAL_SERVER_ERROR) else: result, status_code = esec_client.reissue_sms( borrower.esec_user_name) if status_code != 200: application.app.logger.error( "Unable to reissue new sms code for esec user: %s", borrower.esec_user_name) abort(status.HTTP_500_INTERNAL_SERVER_ERROR) except: msg = str(sys.exc_info()) application.app.logger.error( "Failed to issue auth code via sms: %s" % msg) abort(status.HTTP_500_INTERNAL_SERVER_ERROR) return status.HTTP_200_OK
def test_update_borrower_signing_in_progress(self, mock_borrower, mock_borrower_save): class ReturnedBorrower: id = 0000000 token = "aaaaaa" deed_token = "aaaaaa" dob = "02/02/1922" phonenumber = "07777777777" signing_in_progress = False mock_borrower.return_value = None mock_borrower_save.signing_in_progress = False with self.assertRaises(BorrowerNotFoundException): Borrower.update_borrower_signing_in_progress('bbbbbb') mock_borrower.return_value = BorrowerModelMock() mock_borrower.return_value.signing_in_progress = True self.assertEqual( Borrower.update_borrower_signing_in_progress('aaaaaa'), True)
def test_borrower_token(self): token = Borrower.generate_token() char_list = ['I', 'O', 'W', 'Z'] res = False if any((c in char_list) for c in token): res = True self.assertTrue(token.isupper()) self.assertFalse(res)
def auth_sms(deed_reference, borrower_token, borrower_code): deed = Deed.get_deed(deed_reference) if deed is None: LOGGER.error("Database Exception 404 for deed reference - %s" % deed_reference) abort(status.HTTP_404_NOT_FOUND) else: LOGGER.info( "Signing deed for borrower_token %s against deed reference %s" % (borrower_token, deed_reference)) # check if XML already exist if deed.deed_xml is None: LOGGER.info("Generating DEED_XML") deed_XML = convert_json_to_xml(deed.deed) deed.deed_xml = deed_XML.encode("utf-8") try: LOGGER.info("getting existing XML") modify_xml = copy.deepcopy(deed.deed_xml) borrower_pos = deed.get_borrower_position(borrower_token) borrower = Borrower.get_by_token(borrower_token) esec_id = borrower.esec_user_name if esec_id: result_xml, status_code = esec_client.auth_sms( modify_xml, borrower_pos, esec_id, borrower_code) LOGGER.info("signed status code: %s", str(status_code)) LOGGER.info("signed XML: %s" % result_xml) if status_code == 200: deed.deed_xml = result_xml LOGGER.info("Saving XML to DB") deed.save() LOGGER.info("updating JSON with Signature") deed.deed = update_deed_signature_timestamp( deed, borrower_token) else: LOGGER.error("Failed to sign Mortgage document") return "Failed to sign Mortgage document", status_code else: LOGGER.error( "Failed to sign Mortgage document - unable to create user") abort(status.HTTP_500_INTERNAL_SERVER_ERROR) except: msg = str(sys.exc_info()) LOGGER.error("Failed to sign Mortgage document: %s" % msg) abort(status.HTTP_500_INTERNAL_SERVER_ERROR) return jsonify({"deed": deed.deed}), status.HTTP_200_OK
def auth_sms(deed_reference, borrower_token, borrower_code): deed = Deed.get_deed(deed_reference) if deed is None: LOGGER.error("Database Exception 404 for deed reference - %s" % deed_reference) abort(status.HTTP_404_NOT_FOUND) else: LOGGER.info("Signing deed for borrower_token %s against deed reference %s" % (borrower_token, deed_reference)) # check if XML already exist if deed.deed_xml is None: LOGGER.info("Generating DEED_XML") deed_XML = convert_json_to_xml(deed.deed) deed.deed_xml = deed_XML.encode("utf-8") try: LOGGER.info("getting existing XML") modify_xml = copy.deepcopy(deed.deed_xml) borrower_pos = deed.get_borrower_position(borrower_token) borrower = Borrower.get_by_token(borrower_token) esec_id = borrower.esec_user_name if esec_id: result_xml, status_code = esec_client.auth_sms(modify_xml, borrower_pos, esec_id, borrower_code) LOGGER.info("signed status code: %s", str(status_code)) LOGGER.info("signed XML: %s" % result_xml) if status_code == 200: deed.deed_xml = result_xml LOGGER.info("Saving XML to DB") deed.save() LOGGER.info("updating JSON with Signature") deed.deed = update_deed_signature_timestamp(deed, borrower_token) else: LOGGER.error("Failed to sign Mortgage document") return "Failed to sign Mortgage document", status_code else: LOGGER.error("Failed to sign Mortgage document - unable to create user") abort(status.HTTP_500_INTERNAL_SERVER_ERROR) except: msg = str(sys.exc_info()) LOGGER.error("Failed to sign Mortgage document: %s" % msg) abort(status.HTTP_500_INTERNAL_SERVER_ERROR) return jsonify({"deed": deed.deed}), status.HTTP_200_OK
def get_borrower_details_by_verify_pid(verify_pid): borrower = Borrower.get_by_verify_pid(verify_pid) if borrower is not None: return json.dumps( { "borrower_token": borrower.token, "deed_token": borrower.deed_token, "phone_number": borrower.phonenumber, "borrower_id": borrower.id, "signing_in_progress": borrower.signing_in_progress } ), status.HTTP_200_OK return "Matching borrower not found", status.HTTP_404_NOT_FOUND
def validate_borrower(): payload = request.get_json() if 'borrower_token' in payload: borrower = Borrower.get_by_token(payload['borrower_token'].strip()) if borrower is not None: input_dob = datetime.strptime(payload['dob'], "%d/%m/%Y") db_dob = datetime.strptime(borrower.dob, "%d/%m/%Y") if input_dob == db_dob: stripped_number = strip_number_to_four_digits(borrower.phonenumber) return json.dumps({"deed_token": borrower.deed_token, "phone_number": stripped_number}),\ status.HTTP_200_OK return "Matching deed not found", status.HTTP_404_NOT_FOUND
def validate_borrower(): payload = request.get_json() if 'borrower_token' in payload: borrower = Borrower.get_by_token(payload['borrower_token'].strip()) if borrower is not None: input_dob = datetime.strptime(payload['dob'], "%d/%m/%Y") db_dob = datetime.strptime(borrower.dob, "%d/%m/%Y") if input_dob == db_dob: stripped_number = strip_number_to_four_digits( borrower.phonenumber) return json.dumps({"deed_token": borrower.deed_token, "phone_number": stripped_number}),\ status.HTTP_200_OK return "Matching deed not found", status.HTTP_404_NOT_FOUND
def validate_borrower(): payload = request.get_json() if 'borrower_token' in payload: borrower = Borrower.get_by_token(payload['borrower_token'].strip()) if borrower: input_dob = datetime.strptime(payload['dob'], "%d/%m/%Y") db_dob = datetime.strptime(borrower.dob, "%d/%m/%Y") if input_dob == db_dob: borrower_id = borrower.id return json.dumps({"deed_token": borrower.deed_token, "phone_number": borrower.phonenumber, "borrower_id": borrower_id}),\ status.HTTP_200_OK else: application.app.logger.error("Matching DOB not found for provided borrower.") return "Matching deed not found", status.HTTP_404_NOT_FOUND
def issue_sms(deed_reference, borrower_token): deed = Deed.get_deed(deed_reference) if deed is None: LOGGER.error("Database Exception 404 for deed reference - %s" % deed_reference) abort(status.HTTP_404_NOT_FOUND) else: LOGGER.info("Signing deed for borrower_token %s against deed reference %s" % (borrower_token, deed_reference)) try: LOGGER.info("getting existing XML") borrower = Borrower.get_by_token(borrower_token) if not borrower.esec_user_name: LOGGER.info("creating esec user for borrower[token:%s]", borrower.token) user_id, status_code = esec_client.issue_sms(borrower.forename, borrower.surname, deed.organisation_id, borrower.phonenumber) if status_code == 200: LOGGER.info("Created new esec user: %s for borrower[token:%s]", str(user_id.decode()), borrower.token) borrower.esec_user_name = user_id.decode() borrower.save() else: LOGGER.error("Unable to create new e-sec user for borrower [token:%s]", borrower.token) abort(status.HTTP_500_INTERNAL_SERVER_ERROR) else: result, status_code = esec_client.reissue_sms(borrower.esec_user_name) if status_code != 200: LOGGER.error("Unable to reissue new sms code for esec user: %s", borrower.esec_user_name) abort(status.HTTP_500_INTERNAL_SERVER_ERROR) except: msg = str(sys.exc_info()) LOGGER.error("Failed to issue auth code via sms: %s" % msg) abort(status.HTTP_500_INTERNAL_SERVER_ERROR) return status.HTTP_200_OK
def saveBorrower(self, borrower, deed_token): borrowerModel = Borrower() borrowerModel.forename = borrower['forename'] if 'middle_name' in borrower: borrowerModel.middlename = borrower['middle_name'] borrowerModel.surname = borrower['surname'] borrowerModel.dob = borrower['dob'] borrowerModel.deed_token = deed_token if 'gender' in borrower: borrowerModel.gender = borrower['gender'] borrowerModel.phonenumber = borrower['phone_number'] borrowerModel.address = borrower['address'] borrowerModel.token = borrowerModel.generate_token() borrowerModel.save() return borrowerModel
def auth_sms(deed, borrower_pos, user_id, borrower_auth_code, borrower_token): # pragma: no cover application.app.logger.info("Calling dm-esec-client to verify OTP code and sign the deed") element_id = 'deedData' borrower_path = "/dm-application/operativeDeed/signatureSlots" parameters = { 'borrower-pos': borrower_pos, 'element-id': element_id, 'borrowers-path': borrower_path, 'user-id': user_id, 'otp-code': borrower_auth_code, 'service-id': 1 } extra_parameters = { 'borrower-token': borrower_token, 'datetime': datetime.datetime.now().strftime("%d %B %Y %I:%M%p"), 'deed-id': deed.token } application.app.logger.info("Calling esec_client to hit validateSMSOTP...") request_url = config.ESEC_CLIENT_BASE_HOST + "/esec/auth_sms" resp = requests.post(request_url, params=parameters, data=deed.deed_xml) if resp.status_code == status.HTTP_401_UNAUTHORIZED: application.app.logger.info("Response status = %s" % resp.status_code) return jsonify({"status": "SMS Invalid"}), resp.status_code elif resp.status_code == status.HTTP_200_OK: application.app.logger.info("Response status = %s" % resp.status_code) deed_xml_to_send = deed.deed_xml.decode('utf-8') application.app.logger.info("Hashing deed prior to sending message to queue...") tree = etree.fromstring(deed.deed_xml) deed_data_xml = tree.xpath('.//deedData')[0] deed.deed_hash = Deed().generate_hash(etree.tostring(deed_data_xml)) deed.save() application.app.logger.info("Preparing to send message to the queue...") try: url = broker_url(config.RABBIT_HOST, config.EXCHANGE_USER, config.EXCHANGE_PASS, 5672, config.RABBIT_VHOST) with Emitter(url, config.EXCHANGE_NAME, config.ROUTING_KEYS) as emitter: emitter.send_message({'params': parameters, 'extra-parameters': extra_parameters, 'data': deed_xml_to_send}) application.app.logger.info("Message sent to the queue...") Borrower.update_borrower_signing_in_progress(borrower_token) return jsonify({"status": "Message successfully sent to the queue"}), status.HTTP_200_OK except Exception as e: application.app.logger.info('Error returned when trying to place an item on the queue: %s' % e) raise Exception else: application.app.logger.error("ESecurity Client Exception when trying to verify the OTP code") abort(status.HTTP_500_INTERNAL_SERVER_ERROR)
def remove_borrower_row(self, borrower_id): with self.app.app_context(): borrower = Borrower() borrower.delete(999)
def insert_borrower_row(self, verify_pid, borrower_id): with self.app.app_context(): remove_verify_match_row(self, 999) remove_borrower_row(self, 999) borrower = Borrower() borrower.id = 999 borrower.forename = 'some' borrower.middlename = 'nice' borrower.surname = 'guy' borrower.dob = 'a date' borrower.gender = 'a gender' borrower.phonenumber = '07777777777' borrower.address = 'an address' borrower.token = 'a token' borrower.deed_token = 'a deed token' borrower.esec_user_name = 'an esec user name' borrower.save()
def borrower_object_helper(borrower): new_borrower = Borrower() new_borrower.id = borrower['id'] new_borrower.token = "AAAA" new_borrower.deed_token = "AAAA" new_borrower.forename = borrower['forename'] new_borrower.middlename = borrower['middle_name'] new_borrower.surname = borrower['surname'] new_borrower.dob = borrower['dob'] new_borrower.gender = borrower['gender'] new_borrower.phonenumber = borrower['phone_number'] new_borrower.address = borrower['address'] new_borrower.esec_user_name = "" return new_borrower
def check_borrower_signing_in_progress(borrower_token): borrower = Borrower.get_by_token(borrower_token) if borrower: return jsonify({'result': borrower.signing_in_progress}), status.HTTP_200_OK return "Matching borrower not found", status.HTTP_404_NOT_FOUND
def get_existing_deed_and_update(deed_reference): deed = Deed() deed_update_json = request.get_json() validator = Validation() credentials = validator.validate_organisation_credentials() if credentials is None: return '', status.HTTP_401_UNAUTHORIZED schema_errors = validator.validate_payload(deed_update_json) ids = [] for borrower in deed_update_json["borrowers"]: if 'id' in borrower: ids.append(borrower['id']) duplicates = [ item for item, count in collections.Counter(ids).items() if count > 1 ] if duplicates: schema_errors.append("A borrower ID must be unique to an individual.") if schema_errors: compiled_list = send_error_list(schema_errors) return compiled_list error_list = [] result_deed = deed.get_deed(deed_reference) if result_deed is None: error_list.append("There is no deed associated with - %s deed id." % str(deed_reference)) application.app.logger.error("Deed with reference - %s not found" % str(deed_reference)) return_error_list = send_error_list(error_list) return return_error_list # Deed Status checks if str(result_deed.status) != "DRAFT": error_list.append( "This deed is not in the correct state to be modified.") return_error_list = send_error_list(error_list) return return_error_list for borrower_id in ids: borrower_check = Borrower.get_by_id(borrower_id) if borrower_check is None or borrower_check.deed_token != deed_reference: error_list.append( "Borrowers provided do not match the selected deed.") return_error_list = send_error_list(error_list) return return_error_list validate_title_number = validator.validate_title_number(deed_update_json) if validate_title_number != "title OK": error_list.append(validate_title_number) return_error_list = send_error_list(error_list) return return_error_list # From here - errors are grouped error_list = [] validate_borrower_names, msg = validator.validate_borrower_names( deed_update_json) if not validate_borrower_names: error_list.append(msg) modify_deed_akuma = validator.call_akuma( deed_update_json, result_deed.token, credentials['organisation_name'], credentials['organisation_locale'], deed_type="modify deed") if modify_deed_akuma['result'] == "Z": return jsonify({"message": "Unable to use this service. " "This might be because of technical difficulties or entries on the register not " "being suitable for digital applications. " "You will need to complete this transaction using a paper deed."}), \ status.HTTP_403_FORBIDDEN dob_validate, msg = validator.validate_dob(deed_update_json) if not dob_validate: error_list.append(msg) phone_validate, msg = validator.validate_phonenumbers(deed_update_json) if not phone_validate: error_list.append(msg) md_validate, msg = validator.validate_md_exists(deed_update_json['md_ref']) if not md_validate: error_list.append(msg) # Error List Print Out if len(error_list) > 0: compiled_list = send_error_list(error_list) return compiled_list success, msg = update_deed(result_deed, deed_update_json) if not success: application.app.logger.error("Update deed 400_BAD_REQUEST") return msg, status.HTTP_400_BAD_REQUEST else: application.app.logger.info("Deed has been updated successfully.") return jsonify({"path": '/deed/' + str(deed_reference)}), status.HTTP_200_OK
def auth_sms(deed_reference, borrower_token, borrower_code): deed_instance = Deed() deed = deed_instance.get_deed(deed_reference) if deed is None: application.app.logger.error( "Database Exception 404 for deed reference - %s" % deed_reference) abort(status.HTTP_404_NOT_FOUND) else: application.app.logger.info( "Signing deed for borrower_token %s against deed reference %s" % (borrower_token, deed_reference)) signing_deed_akuma = Akuma.do_check(deed.deed, "borrower sign", deed.organisation_name, "", deed.token) application.app.logger.info("Check ID - Borrower SIGNING: " + signing_deed_akuma['id']) if signing_deed_akuma["result"] == "Z": application.app.logger.error("Failed to sign Mortgage document") return "Failed to sign Mortgage document" # check if XML already exist if deed.deed_xml is None: application.app.logger.info("Generating DEED_XML") deed_XML = convert_json_to_xml(deed.deed) deed.deed_xml = deed_XML.encode("utf-8") try: application.app.logger.info("getting existing XML") borrower_pos = deed.get_borrower_position(borrower_token) borrower = Borrower.get_by_token(borrower_token) esec_id = borrower.esec_user_name if esec_id: esec_client = make_esec_client() response, status_code = esec_client.auth_sms( deed, borrower_pos, esec_id, borrower_code, borrower_token) application.app.logger.info("auth_sms status code: %s", str(status_code)) if status_code == 200: return jsonify({"deed": deed.deed}), status.HTTP_200_OK else: application.app.logger.error( "Failed to authenticate sms code") return jsonify({ "status": "Failed to authenticate sms code" }), status.HTTP_401_UNAUTHORIZED else: application.app.logger.error( "Failed to sign Mortgage document - unable to create user") abort(status.HTTP_500_INTERNAL_SERVER_ERROR) except: msg = str(sys.exc_info()) application.app.logger.error( "Failed to sign Mortgage document: %s" % msg) abort(status.HTTP_500_INTERNAL_SERVER_ERROR) return jsonify({"deed": deed.deed}), status.HTTP_200_OK