Пример #1
0
def reward_address_for_task_internal(public_address, task_id, send_push,
                                     user_id, memo):
    '''transfer the correct amount of kins for the task to the given address
    
       this function runs in the background and sends a push message to the client to
       indicate that the money was indeed transferred.
    '''
    # get reward amount from db
    amount = get_reward_for_task(task_id)
    if not amount:
        print('could not figure reward amount for task_id: %s' % task_id)
        raise InternalError('cant find reward for taskid %s' % task_id)
    try:
        # send the moneys
        print('calling send_kin: %s, %s' % (public_address, amount))
        tx_hash = send_kin(public_address, amount, memo)
    except Exception as e:
        print('caught exception sending %s kins to %s - exception: %s:' %
              (amount, public_address, e))
        raise InternalError('failed sending %s kins to %s' %
                            (amount, public_address))
    finally:  #TODO dont do this if we fail with the tx
        if send_push:
            send_push_tx_completed(user_id, tx_hash, amount, task_id)
        create_tx(tx_hash, user_id, public_address, False, amount, {
            'task_id': task_id,
            'memo': memo
        })  # TODO Add memeo?
Пример #2
0
def finalize_good(order_id, tx_hash):
    """mark this good as used-up. return True on success"""
    good_res = {}
    try:
        # lock the line until the commit is complete
        good = db.session.query(Good).filter(
            Good.order_id == order_id).with_for_update().one()
        if not good:
            # should never happen
            raise InternalError(
                'cant finalize good: good with order_id: %s not found' %
                order_id)
        else:
            good_res['type'] = good.good_type
            good_res['value'] = good.value
            good.tx_hash = tx_hash
            db.session.add(good)
            db.session.commit()
            db.session.flush()
    except Exception as e:
        db.session.rollback()
        log.error('failed to finalize good with order_id: %s. exception: %s' %
                  (order_id, e))
        raise InternalError('cant finalize good for order_id: %s' % order_id)
    else:
        return True, good_res
Пример #3
0
def delete_order(order_id):
    '''delete an order'''
    try:
        deleted_count = Order.query.filter_by(order_id=order_id).delete()
        if deleted_count != 1:
            # should never happen
            raise InternalError(
                'deleted %s orders while trying to delete order-id:%s' %
                (deleted_count, order_id))
    except Exception as e:
        raise InternalError('failed to delete an order with id %s' % order_id)
Пример #4
0
def create_good(offer_id, good_type, value, extra_info=None):
    """creates a new good-instance for the given offer_id with the given value"""
    if not offer_id:
        log.error('refusing to create good with offer_id: %s' % offer_id)
        return False

    if does_code_exist(value):
        log.error(
            'refusing to create good with code: %s as it already exists in the db'
            % value)
        return False

    try:
        now = arrow.utcnow()
        good = Good()
        good.offer_id = offer_id
        good.good_type = good_type
        good.value = value
        good.created_at = now
        if extra_info:
            good.extra_info = extra_info

        db.session.add(good)
        db.session.commit()
    except Exception as e:
        log.error('failed to create a new good. e:%s' % e)
        raise InternalError('failed to create a new good')
    else:
        return True
Пример #5
0
def reward_address_for_task(public_address, task_id):
    '''transfer the correct amount of kins for the task to the given address'''
    # get reward amount
    amount = get_reward_for_task(task_id)
    if not amount:
        print('could not figure reward amount for task_id: %s' % task_id)
        raise InternalError('cant find reward for taskid %s' % task_id)
    try:
        print('calling send_kin: %s, %s' % (public_address, amount))
        tx_hash = stellar.send_kin(public_address, amount, 'kin-app')#-taskid:%s' % task_id)
        print('tx_has: %s' % tx_hash)
        print('after calling send_kin')
    except Exception as e:
        print('caught exception sending %s kins to %s - exception: %s:' % (amount, public_address, e))
        raise InternalError('failed sending %s kins to %s' % (amount, public_address))
    return tx_hash, amount
Пример #6
0
def onboard_user():
    '''creates a wallet for the user and deposits some xlms there'''
    # input sanity
    try:
        user_id = extract_header(request)
        public_address = request.get_json(silent=True).get(
            'public_address', None)
        if None in (public_address, user_id):
            raise InvalidUsage('bad-request')
    except Exception as e:
        raise InvalidUsage('bad-request')

    # ensure the user exists but does not have an account:
    onboarded = is_onboarded(user_id)
    if onboarded is True:
        raise InvalidUsage('user already has an account')
    elif onboarded is None:
        raise InvalidUsage('no such user exists')
    else:
        # create an account, provided none is already being created
        lock = redis_lock.Lock(app.redis, 'address:%s' % public_address)
        if lock.acquire(blocking=False):
            try:
                print('creating account with address %s and amount %s' %
                      (public_address, config.STELLAR_INITIAL_ACCOUNT_BALANCE))
                tx_id = create_account(public_address,
                                       config.STELLAR_INITIAL_ACCOUNT_BALANCE)
                if (tx_id):
                    set_onboarded(user_id, True)
                else:
                    raise InternalError('failed to create account at %s' %
                                        public_address)
            except Exception as e:
                print('exception trying to create account:%s' % e)
                raise InternalError('unable to create account')
            else:
                print('created account %s with txid %s' %
                      (public_address, tx_id))
            finally:
                lock.release()
        else:
            raise InvalidUsage(
                'already creating account for user_id: %s and address: %s' %
                (user_id, public_address))

        increment_metric('user_onboarded')
        return jsonify(status='ok')
Пример #7
0
def update_task_time(task_id, time_string):
    '''debug function used to update existing tasks's time in the db'''
    task = Task.query.filter_by(task_id=task_id).first()
    if not task:
        raise InternalError('no such task_id')
    task.start_date = time_string
    db.session.add(task)
    db.session.commit()
Пример #8
0
def create_order(user_id, offer_id):
    '''creates a new order and allocate the goods for it'''

    # dont let users create too many simultaneous orders
    if len(get_orders_for_user(user_id)) >= int(
            config.MAX_SIMULTANEOUS_ORDERS_PER_USER):
        print('rejecting users ofer - too many orders')
        return None, utils.ERROR_ORDERS_COOLDOWN

    # get offer cost
    kin_amount, address = get_cost_and_address(offer_id)
    if None in (kin_amount, address):
        # should never happen
        raise InternalError('failed to get offer details')

    # make up an order_id
    order_id = KINIT_MEMO_PREFIX + str(
        uuid4())[:ORDER_ID_LENGTH]  #max you can fit inside a stellar memo

    # attempt to allocate a good for this order
    if not allocate_good(offer_id, order_id):
        # no good available to allocate. bummer
        print('out of goods for offer_id: %s' % offer_id)
        return None, utils.ERROR_NO_GOODS

    try:
        order = Order()
        order.order_id = order_id
        order.user_id = user_id
        order.offer_id = offer_id
        order.kin_amount = kin_amount
        order.address = address
        order.created_at = arrow.utcnow()
        db.session.add(order)
        db.session.commit()
    except Exception as e:
        print('failed to create a new order with id %s' % order_id)
        raise InternalError('failed to create a new order')
    else:
        return str(order_id), None
Пример #9
0
def create_order(user_id, offer_id):
    """creates a new order and allocate the goods for it"""

    # dont let users create too many simultaneous orders
    if len(get_orders_for_user(user_id)) >= int(
            config.MAX_SIMULTANEOUS_ORDERS_PER_USER):
        log.error('rejecting users ofer - too many orders')
        return None, utils.ERROR_ORDERS_COOLDOWN

    # get offer cost
    kin_amount, address = get_cost_and_address(offer_id)
    if None in (kin_amount, address):
        # should never happen
        raise InternalError('failed to get offer details')

    # make up an order_id
    order_id = utils.generate_memo()

    # attempt to allocate a good for this order
    if not allocate_good(offer_id, order_id):
        # no good available to allocate. bummer
        log.info('out of goods for offer_id: %s' % offer_id)
        return None, utils.ERROR_NO_GOODS

    try:
        order = Order()
        order.order_id = order_id
        order.user_id = user_id
        order.offer_id = offer_id
        order.kin_amount = kin_amount
        order.address = address
        order.created_at = arrow.utcnow()
        db.session.add(order)
        db.session.commit()
    except Exception as e:
        log.error('failed to create a new order with id %s. e: %s' %
                  (order_id, e))
        raise InternalError('failed to create a new order')
    else:
        return str(order_id), None
Пример #10
0
def should_apply_cooldown(ordered_task_results):
    '''return True if cooldown is needed.
    
       cooldown is defined as time since the last time task results were submitted.
    '''
    if not ordered_task_results:
        # should not happened, as checked before
        raise InternalError('no task results were passed')
    else:
        if (arrow.utcnow() - arrow.get(ordered_task_results[-1].update_at)).total_seconds() < 24*60*60:
            print('cooldown needed. last submission: %s, total seconds ago: %s' % (ordered_task_results[-1].update_at, (arrow.utcnow() - arrow.get(ordered_task_results[-1].update_at)).total_seconds()))
            return True
        return False
Пример #11
0
def get_encrpytion_creds():
    """returns the encrpytion/decryption key and iv from ssm"""
    env = os.environ.get('ENV', 'test')
    encryption_key = get_ssm_parameter('/config/' + env + '/encryption/key',
                                       config.KMS_KEY_AWS_REGION)
    iv = bytes.fromhex(
        get_ssm_parameter(
            '/config/' + env + '/encryption/iv',
            config.KMS_KEY_AWS_REGION))  # the iv is encoded into hex()
    if not encryption_key:
        log.error('cant get encryption_creds')
        raise InternalError('cant get encryption_creds')

    return encryption_key, iv
Пример #12
0
def create_good(offer_id, good_type, value):
    '''creates a new good-instance for the given offer_id with the given value'''
    try:
        now = arrow.utcnow()
        good = Good()
        good.offer_id = offer_id
        good.good_type = good_type
        good.value = value
        good.created_at = now
        db.session.add(good)
        db.session.commit()
    except Exception as e:
        print('failed to create a new good')
        print(e)
        raise InternalError('failed to create a new good')
    else:
        return True
def create_bh_card(card_id, order_id, merchant_code, denomination):
    """creates a new instance of BlackhawkCard"""
    try:

        card = BlackhawkCard()
        card.card_id = card_id
        card.order_id = order_id
        card.merchant_code = merchant_code
        card.denomination = denomination

        db.session.add(card)
        db.session.commit()
    except Exception as e:
        log.error('failed to create a new blackhawk card with id: %s. e:%s' %
                  (card_id, e))
        raise InternalError('failed to create a new blackhawk card')
    else:
        return True
Пример #14
0
def get_truex_creds(force_prod=False):
    env = os.environ.get('ENV', 'test')

    if force_prod:
        print('forcing prod truex creds')
        env = 'prod'

    partner_hash = get_ssm_parameter('/config/' + env + '/truex/partner_hash',
                                     config.KMS_KEY_AWS_REGION)
    callback_secret = get_ssm_parameter(
        '/config/' + env + '/truex/callback_secret', config.KMS_KEY_AWS_REGION)
    app_id = get_ssm_parameter('/config/' + env + '/truex/app_id',
                               config.KMS_KEY_AWS_REGION)
    if None in (app_id, partner_hash, callback_secret):
        log.error('cant get truex creds')
        raise InternalError('cant get truex creds')

    return app_id, partner_hash, callback_secret
Пример #15
0
def user_phone_number_blacklist_endpoint():
    """blacklist a number"""
    if not config.DEBUG:
        limit_to_localhost()

    try:
        payload = request.get_json(silent=True)
        phone_number = payload.get('phone-number', None)
        if phone_number is None:
            print('user_phone_number_blacklist_endpoint: user_phone: %s' %
                  phone_number)
            raise InvalidUsage('bad-request')
    except Exception as e:
        print(e)
        raise InvalidUsage('bad-request')

    if not blacklist_phone_number(phone_number):
        raise InternalError('cant blacklist number')
    return jsonify(status='ok')
Пример #16
0
def create_bh_offer(offer_id, merchant_code, merchant_template_id, batch_size,
                    denomination, minimum_threshold):
    """creates a new instance of BlackhawkCard"""
    try:

        offer = BlackhawkOffer()
        offer.offer_id = offer_id
        offer.merchant_code = merchant_code
        offer.merchant_template_id = merchant_template_id
        offer.batch_size = batch_size
        offer.denomination = denomination
        offer.minimum_threshold = minimum_threshold

        db.session.add(offer)
        db.session.commit()
    except Exception as e:
        log.error('failed to create a new blackhawk offer with id: %s. e: %s' %
                  (offer, e))
        raise InternalError('failed to create a new blackhawk offer')
    else:
        return True
Пример #17
0
def allocate_good(offer_id, order_id):
    '''find and allocate a good to an order. 
       returns the good sid on success or None if no goods are available'''

    #TODO ensure the order hasn't expired?

    try:
        # lock the line until the commit is complete
        good = db.session.query(Good).filter(Good.offer_id==offer_id).filter(Good.order_id==None).with_for_update().first()
        if not good:
            return None
        good.order_id = order_id
        db.session.add(good)
        db.session.commit()
        db.session.flush()
    except Exception as e:
        db.session.rollback()
        print('failed to allocate good with order_id: %s. exception: %s' % (order_id,e))
        raise InternalError('cant allocate good for order_id: %s' % order_id)
    else:
        return good.sid
Пример #18
0
def store_task_results(user_id, task_id, results):
    """store the results provided by the user"""
    # reject hackers trying to send task results too soon

    try:
        # store the results

        try:
            user_task_results = UserTaskResults()
            user_task_results.user_id = user_id
            user_task_results.task_id = task_id
            user_task_results.results = results
            db.session.add(user_task_results)
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            # this code handles the unlikely event that a user already had task results for this task, so rather
            # than INSERT, we UPDATE.
            log.info('store_task_results - failed to insert results. attempting to update instead. error:%s' % e)
            previous_task_results = UserTaskResults.query.filter_by(user_id=user_id).filter_by(task_id=task_id).first()
            previous_task_results.results = results
            db.session.add(previous_task_results)
            db.session.commit()
            log.info('store_task_results: overwritten user_id %s task %s results' % (user_id, task_id))
            increment_metric('overwrite-task-results')

        # write down the completed task-id
        from kinappserver.models import UserAppData
        user_app_data = UserAppData.query.filter_by(user_id=user_id).first()
        if user_app_data is None:
            log.error('cant retrieve user app data for user:%s' % user_id)
            raise InternalError('cant retrieve user app data for user:%s' % user_id)

        cat_id = get_cat_id_for_task_id(task_id)
        if not cat_id:
            log.error('cant find cat_id for task_id %s' % task_id)
            raise InternalError('cant find cat_id for task_id %s' % task_id)

        if cat_id in user_app_data.completed_tasks_dict:
            if task_id not in user_app_data.completed_tasks_dict[cat_id]:
                user_app_data.completed_tasks_dict[cat_id].append(task_id)
        else:
            user_app_data.completed_tasks_dict[cat_id] = [task_id]

        commit_json_changed_to_orm(user_app_data, ['completed_tasks_dict'])

        log.info('wrote user_app_data.completed_tasks for userid: %s' % user_id)

        # calculate the next valid submission time, and store it:
        delay_days = None
        # calculate the next task's valid submission time, and store it:
        # this takes into account the delay_days field on the next task.

        # note: even if we end up skipping the next task (for example, truex for iOS),
        # we should still use the original delay days value (as done here).

        try:
            delay_days = get_next_task_delay_days(user_id, task_id)  # throws exception if no such task exists
            print('next task delay:%s (user_id: %s, current task: %s)' % (delay_days, user_id, task_id))
        except Exception as e:
            log.error('cant find task_delay for next task_id of %s' % task_id)

        if delay_days is None or int(delay_days) == 0:
            shifted_ts = arrow.utcnow().timestamp
            log.info('setting next task time to now (delay_days is: %s)' % delay_days)
        else:
            shift_seconds = calculate_timeshift(user_id, delay_days)
            shifted_ts = arrow.utcnow().shift(seconds=shift_seconds).timestamp
            log.info('setting next task time to %s seconds in the future' % shift_seconds)

        log.info('next valid submission time for user %s, (previous task id %s) in shifted_ts: %s' % (user_id, task_id, shifted_ts))

        store_next_task_results_ts(user_id, task_id, shifted_ts)

        return True
    except Exception as e:
        log.error('exception in store_task_results: %s', e)
        raise InvalidUsage('cant store_task_results')
Пример #19
0
def get_reward_for_task(task_id):
    """return the amount of kin reward associated with this task"""
    task = Task2.query.filter_by(task_id=task_id).first()
    if not task:
        raise InternalError('no such task_id: %s' % task_id)
    return task.price
Пример #20
0
def get_task_delay(task_id):
    """return the amount of delay associated with this task"""
    task = Task2.query.filter_by(task_id=task_id).first()
    if not task:
        raise InternalError('no such task_id: %s' % task_id)
    return task.delay_days
Пример #21
0
def get_task_type(task_id):
    """get the tasks type"""
    task = Task2.query.filter_by(task_id=task_id).first()
    if not task:
        raise InternalError('no such task_id: %s' % task_id)
    return task.task_type
Пример #22
0
def get_reward_for_task(task_id):
    '''return the amount of kin reward associated with this task'''
    task = Task.query.filter_by(task_id=task_id).first()
    if not task:
        raise InternalError('no such task_id')
    return task.kin_reward