def recipes_requirements_satisfied(): # find out who's calling this endpoint token = get_token_auth_header() user_info = get_user_info(token) email = user_info['email'] # then get POSTed form data table = dynamodb.Table("users") response = table.query( KeyConditionExpression=Key("email").eq(email) ) data = { "tbank": False, "ocbc": False, "dbs": False, } accounts = response['Items'][0]['accounts'] if "tbank" in accounts: data['tbank'] = True if "ocbc" in accounts: data['ocbc'] = True if "dbs" in accounts: data['dbs'] = True return jsonify({"status": 200, "data": data}), 200
def recipes_create(): # find out who's calling this endpoint token = get_token_auth_header() user_info = get_user_info(token) # then get POSTed form data data = request.get_json() taskName = data['taskName'] table = dynamodb.Table("scheduled_tasks") if taskName == "tbank.salary.transfer": response = table.update_item( Key={ 'email': user_info['email'], 'task_name': 'tbank.salary.transfer', }, UpdateExpression="set #data = :data, #creation = :creation, #expiration = :expiration", ExpressionAttributeNames={ '#data': 'data', '#creation': 'creation_time', '#expiration': 'expiration_time' # this has DynamoDB's TTL attribute }, ExpressionAttributeValues={ ':data': { 'from': data['accountFrom'], 'to': data['accountTo'], 'amount': data['amount'], 'schedule': 'every minute' }, ':creation': int(time.time()), ':expiration': int(time.time()) + 60 # 1 week is 3600*24*7 }, ReturnValues="ALL_NEW" ) elif taskName == "smartfin.aggregated_email": response = table.update_item( Key={ 'email': user_info['email'], 'task_name': 'smartfin.aggregated_email', }, UpdateExpression="set #data = :data, #creation = :creation, #expiration = :expiration", ExpressionAttributeNames={ '#data': 'data', '#creation': 'creation_time', '#expiration': 'expiration_time' # this has DynamoDB's TTL attribute }, ExpressionAttributeValues={ ':data': { 'schedule': 'every hour' }, ':creation': int(time.time()), ':expiration': int(time.time()) + 60*60 # 1 week is 3600*24*7 }, ReturnValues="ALL_NEW" ) print(response) return jsonify({"status": 200, "message": "OK"}), 200
def accounts_mfa(): # find out who's calling this endpoint token = get_token_auth_header() user_info = get_user_info(token) # then get POSTed form data data = request.get_json() # request for OTP serviceName = "requestOTP" userID = data['userId'] PIN = data['pin'] header = { "Header": { "serviceName": serviceName, "userID": userID, "PIN": PIN, } } final_url = "{0}?Header={1}".format(url(), json.dumps(header)) response = requests.post(final_url) print(final_url) serviceRespHeader = response.json( )['Content']['ServiceResponse']['ServiceRespHeader'] errorCode = serviceRespHeader['GlobalErrorID'] if errorCode == "010000": logger.info( "{} successfully requested for Multi-Factor Authentication".format( user_info['email'])) return jsonify({ "status": 200, "message": "Your OTP has been sent to the mobile number registered to your bank account." }) elif errorCode == "010041": logger.error( "{} triggered some unknown error in Multi-Factor Authentication". format(user_info['email'])) return jsonify({ "status": 401, "message": "Idk what error is this" }), 401 return jsonify({ "status": 401, "message": "Invalid user ID or PIN, we're unable to send you your OTP." }), 401
def accounts_info(): # find out who's calling this endpoint token = get_token_auth_header() user_info = get_user_info(token) email = user_info['email'] logger.info( "{} has attempted to retrieve their Bank Accounts info".format(email)) table = dynamodb.Table("users") response = table.query(KeyConditionExpression=Key("email").eq(email)) return response['Items'][0]
def tbank_list_user_accounts(): # find out who's calling this endpoint token = get_token_auth_header() user_info = get_user_info(token) # then get POSTed form data data = request.get_json() email = user_info['email'] # Step 1: lookup database for tBank login details first table = dynamodb.Table("users") response = table.query( KeyConditionExpression=Key("email").eq(email) ) accounts = response['Items'][0]['accounts'] # Step 1a: check if tbank exists first if "tbank" not in accounts: return jsonify({"status": 404, "message": "No tBank account was found for the current user."}), 404 # Step 2: prepare login details serviceName = "getCustomerAccounts" userID = accounts['tbank']['userId'] PIN = accounts['tbank']['pin'] OTP = "999999" header = { "Header": { "serviceName": serviceName, "userID": userID, "PIN": PIN, "OTP": OTP } } final_url = "{0}?Header={1}".format(url(), json.dumps(header)) response = requests.post(final_url) print(final_url) serviceResp = response.json()['Content']['ServiceResponse'] serviceRespHeader = serviceResp['ServiceRespHeader'] errorCode = serviceRespHeader['GlobalErrorID'] if errorCode == "010000": logger.info("{} successfully requested for their Accounts List".format( user_info['email'])) accountsList = serviceResp['AccountList']['account'] return jsonify({"status": 200, "data": accountsList}) return jsonify({"status": 401, "message": "Unknown error."}), 401
def accounts_unlink(): # find out who's calling this endpoint token = get_token_auth_header() user_info = get_user_info(token) # then get POSTed form data data = request.get_json() table = dynamodb.Table("users") response = table.update_item(Key={'email': user_info['email']}, UpdateExpression="remove #accounts.#bank", ExpressionAttributeNames={ '#accounts': 'accounts', '#bank': data['name'] }, ReturnValues="ALL_NEW") print(response) return jsonify({"status": 200, "message": "OK"}), 200
def tbank_recipe_salary_transfer_trigger(): # find out who's calling this endpoint token = get_token_auth_header() user_info = get_user_info(token) # then get POSTed form data email = user_info['email'] taskName = "tbank.salary.transfer" table = dynamodb.Table("scheduled_tasks") response = table.delete_item( Key={ 'email': email, 'task_name': taskName, } ) logger.info( "{} requested to manually trigger task {}".format(email, taskName)) return jsonify({"status": 200, "message": "OK"}), 200
def recipes_run_history(): # find out who's calling this endpoint token = get_token_auth_header() user_info = get_user_info(token) email = user_info['email'] # then get POSTed form data table = dynamodb.Table("scheduled_tasks_history") response = table.query( KeyConditionExpression=Key("email").eq(email) ) data = [] tz = pytz.timezone("Asia/Singapore") for i in response['Items']: tmp = ast.literal_eval((json.dumps(i, cls=DecimalEncoder))) tmp['run_time'] = datetime.fromtimestamp( tmp['run_time'], tz).isoformat() data.append(tmp) data = sorted(data, key=lambda k: k['run_time'], reverse=True) return jsonify({"status": 200, "data": data}), 200
def accounts_link(): # find out who's calling this endpoint token = get_token_auth_header() user_info = get_user_info(token) # then get POSTed form data data = request.get_json() # verify with tBank's loginCustomer service, make sure we can login serviceName = "loginCustomer" userID = data['userId'] PIN = data['pin'] OTP = data['otp'] bank = data['bank'] # get bank name e.g. tbank, ocbc, dbs header = { "Header": { "serviceName": serviceName, "userID": userID, "PIN": PIN, "OTP": OTP } } final_url = "{0}?Header={1}".format(url(), json.dumps(header)) response = requests.post(final_url) print(final_url) serviceRespHeader = response.json( )['Content']['ServiceResponse']['ServiceRespHeader'] errorCode = serviceRespHeader['GlobalErrorID'] if errorCode == "010000": LoginOTPAuthenticateResponseObj = response.json( )['Content']['ServiceResponse']['Login_OTP_Authenticate-Response'] logger.info( "{} successfully linked their bank account. customerId {}, bankId {}, bank {}" .format(user_info['email'], LoginOTPAuthenticateResponseObj['CustomerID'], LoginOTPAuthenticateResponseObj['BankID'], bank)) # if can login, we save it to our db, for now... # (not v secure... but tBank doesn't support OAuth) # post data to dynamodb table = dynamodb.Table("users") # TODO add multiple response = table.update_item( Key={'email': user_info['email']}, UpdateExpression="set #accounts.#bankName = :account_info", ExpressionAttributeNames={ '#accounts': 'accounts', '#bankName': bank }, ExpressionAttributeValues={ ':account_info': { "userId": userID, "pin": PIN }, }, ReturnValues="UPDATED_NEW") print(response) print("ok") return jsonify({ "status": 200, "message": "Your bank account is now linked to SmartFIN." }) elif errorCode == "010041": logger.error("OTP has expired. You will receiving a SMS") logger.info("{} failed to linked their bank account. bank {}".format( user_info['email'], bank)) return jsonify({ "status": 401, "message": "Invalid user ID, PIN or OTP." }), 401