Beispiel #1
0
def check_if_node_comes_online(order_key):
    order = order_key.get()  # type: NodeOrder
    order_id = order.id
    if not order.odoo_sale_order_id:
        raise BusinessException(
            'Cannot check status of node order without odoo_sale_order_id')
    node_id = get_node_id_from_odoo(order.odoo_sale_order_id)
    if not node_id:
        raise BusinessException(
            'Could not find node id for sale order %s on odoo' % order_id)

    status = get_node_status(node_id)
    if status == u'running':
        logging.info('Marking node from node order %s as arrived', order_id)
        human_user, app_id = get_app_user_tuple(order.app_user)
        order.populate(arrival_time=now(), status=NodeOrderStatus.ARRIVED)
        order.put()
        deferred.defer(set_node_id_on_profile,
                       order.app_user,
                       node_id,
                       _transactional=True)
        deferred.defer(update_hoster_progress,
                       human_user.email(),
                       app_id,
                       HosterSteps.NODE_POWERED,
                       _transactional=True)
    else:
        logging.info('Node from order %s is not online yet', order_id)
Beispiel #2
0
def get_currency_rate(currency):
    global_stats = GlobalStats.create_key(TOKEN_TFT).get()  # type: GlobalStats
    if currency == 'USD':
        return global_stats.value
    currency_stats = filter(lambda c: c.currency == currency, global_stats.currencies)  # type: list[CurrencyValue]
    if not currency_stats:
        raise BusinessException('No stats are set for currency %s', currency)
    return currency_stats[0].value
Beispiel #3
0
def _fetch(url):
    result = urlfetch.fetch(url)  # type: urlfetch._URLFetchResult
    logging.info('Response from %s: %s %s', url, result.status_code,
                 result.content)
    if result.status_code != 200:
        raise BusinessException('Invalid status from %s: %s' %
                                (url, result.status_code))
    return result.content
Beispiel #4
0
def check_if_node_comes_online(order_key):
    order = order_key.get()  # type: NodeOrder
    order_id = order.id
    if not order.odoo_sale_order_id:
        raise BusinessException(
            'Cannot check status of node order without odoo_sale_order_id')
    nodes = get_nodes_from_odoo(order.odoo_sale_order_id)
    if not nodes:
        raise BusinessException(
            'Could not find nodes for sale order %s on odoo' % order_id)

    statuses = get_nodes_status([n['id'] for n in nodes])
    if all([status == 'running' for status in statuses]):
        iyo_username = get_iyo_username(order.app_user)
        _set_node_status_arrived(order_key, iyo_username, nodes)
    else:
        logging.info('Nodes %s from order %s are not all online yet', nodes,
                     order_id)
Beispiel #5
0
def _get_balance_from_transactions(transactions, token):
    # type: (list[ThreeFoldTransaction], unicode) -> WalletBalanceTO
    available_balance = 0
    total_balance = 0
    total_description_details = []
    # TODO set to minimum precision of all transactions when transactions have the 'precision' property
    # (and multiply available / total amount depending on precision)
    precision = 2
    # for transaction in transactions:
    #     precision = max(transaction.precision, precision)

    for transaction in transactions:
        if transaction.token != token:
            raise BusinessException(
                'Invalid transaction supplied to _get_balance_from_transactions. '
                'All transactions must have %s as token', token)
        amount_spent = transaction.amount - transaction.amount_left
        unlocked_amount = 0
        now_ = now()
        for unlock_timestamp, unlock_amount in zip(
                transaction.unlock_timestamps, transaction.unlock_amounts):
            if unlock_timestamp <= now_:
                unlocked_amount += unlock_amount
            else:
                total_description_details.append(
                    (unlock_timestamp, unlock_amount))

        spendable_amount = unlocked_amount - amount_spent

        available_balance += spendable_amount
        total_balance += transaction.amount_left
    if total_description_details:
        total_description = u"""##  %(token)s Unlock times'

|Date|#%(token)s|
|---|---:|
        """ % {
            'token': token
        }
        for unlock_timestamp, unlock_amount in sorted(
                total_description_details, key=lambda tup: tup[0]):
            date = time.strftime('%a %d %b %Y %H:%M:%S GMT',
                                 time.localtime(unlock_timestamp))
            amount = u'{:0,.2f}'.format(unlock_amount / 100.0)
            total_description += u'\n|%s|%s|' % (date, amount)
    else:
        total_description = None
    return WalletBalanceTO(available=available_balance,
                           total=total_balance,
                           description=total_description,
                           token=token,
                           precision=precision)
Beispiel #6
0
def generate_kyc_flow(country_code, iyo_username):
    logging.info('Generating KYC flow for user %s and country %s', iyo_username, country_code)
    flow_params = {'nationality': country_code}
    properties = DEFAULT_KYC_STEPS.union(_get_extra_properties(country_code))
    try:
        known_information = _get_known_information(iyo_username)
        known_information['address_country'] = country_code
    except HttpNotFoundException:
        logging.error('No profile found for user %s!', iyo_username)
        return create_error_message(FlowMemberResultCallbackResultTO())

    steps = []
    branding_key = get_main_branding_hash()
    for prop in properties:
        step_info = _get_step_info(prop)
        if not step_info:
            raise BusinessException('Unsupported step type: %s' % prop)
        value = known_information.get(prop)
        steps.append({
            'reference': 'message_%s' % prop,
            'positive_reference': None,
            'positive_caption': step_info.get('positive_caption', 'Continue'),
            'negative_reference': 'end_premature_end',
            'negative_caption': step_info.get('negative_caption', 'Cancel'),
            'keyboard_type': step_info.get('keyboard_type', 'DEFAULT'),
            'type': step_info.get('widget', 'TextLineWidget'),
            'value': value or step_info.get('value') or '',
            'choices': step_info.get('choices', []),
            'message': step_info['message'],
            'branding_key': branding_key,
            'order': step_info['order']
        })
    sorted_steps = sorted(steps, key=lambda k: k['order'])
    for i, step in enumerate(sorted_steps):
        if len(sorted_steps) > i + 1:
            step['positive_reference'] = sorted_steps[i + 1]['reference']
        else:
            step['positive_reference'] = 'flush_results'
    template_params = {
        'start_reference': sorted_steps[0]['reference'],
        'steps': sorted_steps,
        'language': DEFAULT_LANGUAGE,
        'branding_key': branding_key
    }
    return FLOWS_JINJA_ENVIRONMENT.get_template('kyc_part_2.xml').render(template_params), flow_params
Beispiel #7
0
def _save_transaction_to_backlog(transaction_id, backlog_type):
    return  # Temporarily disabled
    if backlog_type not in ('tierion', 'git'):
        raise Exception('Invalid backlog_type')
    cfg = get_config(NAMESPACE)
    if not (cfg.ledger.url or cfg.ledger.secret):
        if DEBUG:
            logging.warn('Transaction backlog is not filled in, doing nothing')
            return
        raise Exception('Backlog config is not filled in')

    transaction = ThreeFoldTransaction.get_by_id(transaction_id)
    if not transaction:
        raise BusinessException('ThreeFoldTransaction with id %s not found!' %
                                transaction_id)
    data = {
        'id': transaction.id,
        'timestamp': transaction.timestamp,
        'amount': transaction.amount
    }
    if transaction.from_user:
        data['from'] = hmac.new(cfg.ledger.secret.encode(),
                                transaction.from_user.email(),
                                hashlib.sha1).hexdigest()
    if transaction.to_user:
        data['to'] = hmac.new(cfg.ledger.secret.encode(),
                              transaction.to_user.email(),
                              hashlib.sha1).hexdigest()
    headers = {'Authorization': cfg.ledger.secret}
    url = cfg.ledger.url + '/transactions/%s' % backlog_type
    result = urlfetch.fetch(url,
                            json.dumps(data),
                            urlfetch.POST,
                            headers,
                            deadline=30)
    if result.status_code not in (200, 201):
        logging.info('Status:%s Content: %s', result.status_code,
                     result.content)
        raise Exception('Failed to add transaction to backlog')
def _kyc_part_2(message_flow_run_id, member, steps, end_id,
                end_message_flow_id, parent_message_key, tag, result_key,
                flush_id, flush_message_flow_id, service_identity,
                user_details, flow_params):
    parsed_flow_params = json.loads(flow_params)
    applicant = Applicant(nationality=parsed_flow_params['nationality'],
                          addresses=[Address()])
    documents = []
    username = get_iyo_username(user_details[0])
    if not username:
        logging.error('Could not find username for user %s!' % user_details[0])
        return create_error_message()
    profile = get_tff_profile(username)
    result = validate_kyc_status(profile)
    if isinstance(result, FlowMemberResultCallbackResultTO):
        return result

    def _set_attr(prop, value):
        if hasattr(applicant, prop):
            setattr(applicant, prop, value)
        elif prop.startswith('address_'):
            prop = prop.replace('address_', '')
            if prop == 'country':
                applicant.country = value
            setattr(applicant.addresses[0], prop, value)
        else:
            logging.warn('Ignoring unknown property %s with value %s', prop,
                         value)

    for step in steps:
        # In case of the flowcode_check_skip_passport step
        if not isinstance(step, FormFlowStepTO):
            continue
        step_id_split = step.step_id.split('_', 1)
        if step_id_split[0] == 'message':
            prop = step_id_split[
                1]  # 'type' from one of plugins.tff_backend.consts.kyc.kyc_steps
            step_value = step.form_result.result.get_value()
            if prop.startswith('national_identity_card'):
                side = None
                if prop.endswith('front'):
                    side = 'front'
                elif prop.endswith('back'):
                    side = 'back'
                documents.append({
                    'type': 'national_identity_card',
                    'side': side,
                    'value': step_value
                })
            elif prop == 'utility_bill':
                deferred.defer(save_utility_bill,
                               step_value,
                               profile.key,
                               _transactional=True)
            elif prop.startswith('passport'):
                documents.append({'type': 'passport', 'value': step_value})
            elif isinstance(step.form_result.result, UnicodeWidgetResultTO):
                _set_attr(prop, step.form_result.result.value.strip())
            elif isinstance(step.form_result.result, LongWidgetResultTO):
                # date step
                date = datetime.datetime.utcfromtimestamp(step_value).strftime(
                    '%Y-%m-%d')
                _set_attr(prop, date)
            else:
                logging.info('Ignoring step %s', step)
    try:
        if profile.kyc.applicant_id:
            applicant = update_applicant(profile.kyc.applicant_id, applicant)
        else:
            applicant = create_applicant(applicant)
            profile.kyc.applicant_id = applicant.id
    except ApiException as e:
        if e.status in xrange(400, 499):
            raise BusinessException('Invalid status code from onfido: %s %s' %
                                    (e.status, e.body))
        raise
    for document in documents:
        deferred.defer(upload_document,
                       applicant.id,
                       document['type'],
                       document['value'],
                       document.get('side'),
                       _transactional=True)
    profile.kyc.set_status(KYCStatus.SUBMITTED.value, username)
    profile.put()
    deferred.defer(index_profile, Profile.create_key(username))

    # Automatically set status to PENDING_APPROVAL after 5 minutes
    payload = SetKYCPayloadTO(status=KYCStatus.PENDING_APPROVAL.value,
                              comment='Verification started automatically')
    deferred.defer(_set_kyc_status,
                   username,
                   payload,
                   current_user_id=username,
                   _countdown=300,
                   _queue=SCHEDULED_QUEUE)
Beispiel #9
0
def generate_kyc_flow(country_code, iyo_username):
    logging.info('Generating KYC flow for user %s and country %s',
                 iyo_username, country_code)
    flow_params = {'nationality': country_code}
    properties = DEFAULT_KYC_STEPS.union(_get_extra_properties(country_code))
    try:
        known_information = _get_known_information(iyo_username)
        known_information['address_country'] = country_code
    except HttpNotFoundException:
        logging.error('No profile found for user %s!', iyo_username)
        return create_error_message()

    steps = []
    branding_key = get_main_branding_hash()
    must_ask_passport = 'passport' not in REQUIRED_DOCUMENT_TYPES[country_code]
    for prop in properties:
        step_info = _get_step_info(prop)
        if not step_info:
            raise BusinessException('Unsupported step type: %s' % prop)
        value = known_information.get(prop)
        reference = 'message_%s' % prop
        # If yes, go to passport step. If no, go to national identity step
        if prop in ('national_identity_card',
                    'national_identity_card_front') and must_ask_passport:
            steps.append({
                'reference':
                'message_has_passport',
                'message':
                """Are you in the possession of a valid passport?

Note: If you do not have a passport (and only a national id), you will only be able to wire the funds to our UAE Mashreq bank account.""",
                'type':
                None,
                'order':
                step_info['order'] - 0.5,
                'answers': [{
                    'id': 'yes',
                    'caption': 'Yes',
                    'reference': 'message_passport'
                }, {
                    'id':
                    'no',
                    'caption':
                    'No',
                    'reference':
                    'message_national_identity_card'
                    if 'national_identity_card' in properties else
                    'message_national_identity_card_front'
                }]
            })
        steps.append({
            'reference':
            reference,
            'positive_reference':
            None,
            'positive_caption':
            step_info.get('positive_caption', 'Continue'),
            'negative_reference':
            'flush_monitoring_end_canceled',
            'negative_caption':
            step_info.get('negative_caption', 'Cancel'),
            'keyboard_type':
            step_info.get('keyboard_type', 'DEFAULT'),
            'type':
            step_info.get('widget', 'TextLineWidget'),
            'value':
            value or step_info.get('value') or '',
            'choices':
            step_info.get('choices', []),
            'message':
            step_info['message'],
            'branding_key':
            branding_key,
            'order':
            step_info['order']
        })
    sorted_steps = sorted(steps, key=lambda k: k['order'])
    for i, step in enumerate(sorted_steps):
        if len(sorted_steps) > i + 1:
            if 'positive_reference' in step:
                if step['reference'] == 'message_passport':
                    sorted_steps[i - 1][
                        'positive_reference'] = 'flowcode_check_skip_passport'
                step['positive_reference'] = sorted_steps[i + 1]['reference']
        else:
            step['positive_reference'] = 'flush_results'
    template_params = {
        'start_reference': sorted_steps[0]['reference'],
        'steps': sorted_steps,
        'language': DEFAULT_LANGUAGE,
        'branding_key': branding_key
    }
    return FLOWS_JINJA_ENVIRONMENT.get_template('kyc_part_2.xml').render(
        template_params), flow_params