Ejemplo n.º 1
0
def topup(data: TokenData):
    params: TopUp = TopUp(request.args)
    if not params.validate():
        return jsonify({'message': 'Not valid arguments!'}), 400
    curr_str: str = f"{params.currency.data.lower()}_amt"
    session.query(Balance).filter(Balance.customer_id == data.customer_id).update(
        {curr_str: (getattr(Balance, curr_str) + params.amount.data)})
    session.flush()
    session.commit()
    return jsonify({'message': 'TopUp successful!'}), 200
Ejemplo n.º 2
0
def reset_with_token(data: TokenData):
    if request.method == 'POST':
        form: ResetPass = ResetPass(request.form)
        if not form.validate():
            return jsonify({'message': 'Not valid arguments!'}), 400

        # get hash of new password
        hashed_pass: str = get_hash(form.password1.data)
        # Update user's hash pass in DB
        session.query(Password).filter(Password.customer_id == data.customer_id).update({"user_pass": hashed_pass})
        session.flush()
        session.commit()

        return jsonify({'resp': 'success'}), 200
    return render_template('reset_pass.html'), 200
Ejemplo n.º 3
0
def callback(ch, method, properties, body):
    data: InputJson = InputJson(**json.loads(body))
    print(" [x] Received %r" % body)
    # Update user's balance
    session.query(Balance).filter(
        Balance.customer_id == data.customer_id).update({
            data.from_str:
            (getattr(Balance, data.from_str) - data.amount_subtract),
            data.to_str: (getattr(Balance, data.to_str) + data.amount_add)
        })
    session.commit()

    ch.basic_ack(
        delivery_tag=method.delivery_tag
    )  # Answer to RabbitMQ that all is successful => Message is marked as acknowledged
Ejemplo n.º 4
0
def own_transfer(data: TokenData):
    # Get params
    params: CurrencyChangeSchema = CurrencyChangeSchema(request.args)
    if not params.validate():
        return jsonify({'message': 'Not valid arguments!'}), 400

    # Get rate for given pair of currencies
    response = requests.get(f'http://{HOST_CURR_SERV}:{PORT_CURR_SERV}/get_rates',
                            params={'curr_from': params.curr_from.data.upper(), 'curr_to': params.curr_to.data.upper()})
    if response.status_code == 404:
        return jsonify({'message': 'Internal currency service is down'}), 500
    rate: float = response.json()['rate']
    add: float = round(params.amount.data * rate, 2)
    from_str: str = f"{params.curr_from.data.lower()}_amt"
    to_str: str = f"{params.curr_to.data.lower()}_amt"

    # Check if user has enough money on his balance
    cust: Balance = session.query(Balance).filter(Balance.customer_id == data.customer_id).first()
    if getattr(cust, from_str) < params.amount.data:
        return jsonify({'message': 'Not enough money!'}), 400

    publish_message(json_body={'customer_id': data.customer_id,
                               'from_str': from_str,
                               'amount_subtract': params.amount.data,
                               'to_str': to_str,
                               'amount_add': add}, queue='own_transaction')

    return jsonify({'message': 'Success'}), 200
Ejemplo n.º 5
0
        def decorator(*args, **kwargs):

            # hash_pass = session.query(Password).filter(Password.user_email == data).first()

            token = None
            # check if token is in headers
            if 'key' in request.headers:
                token = request.headers['key']
            elif f.__name__ == 'reset_with_token' and 'token' in request.args:
                token = request.args['token']
            if not token:
                return jsonify({'message': 'a valid token is missing'}), 401
            # Try to decode token (only get payload, header and verify signature)
            # How does Electronic signature work:
            # 1. We have message X
            # 2. We calculate hash(x) which is called control sum
            # 3. We encrypt control sum with private key RSA, i.e. encode(hash(X))
            # 4. Receiver gets X + control sum
            # 5. Receiver decodes control sum: decode(encode(hash(X)))=hash(X)
            # 6. Receiver calculates hash(X), where X is received message
            # 7. Compare result from 6 and 7. If equal => legitimate
            try:
                # Get Payload
                data = jwt.decode(
                    token, pub_key,
                    algorithms=[ALG])  # options={"verify_exp": False}
            except ExpiredSignatureError:
                return jsonify(
                    {'message': 'Signature has expired! Try auth method'}), 401
            except:
                return jsonify({'message': 'token is invalid'}), 401

            # Transfer payload to namedtuple
            data = TokenData(**data)

            # This is check only for temporary tokens for Forgot Password. Once password is changed => hash of signature
            # will change. We check that 'signature' parameter in payload matches with hash(customer_id + user_pass_hash +
            # creation_date + token_uuid) Source:
            # https://security.stackexchange.com/questions/153746/one-time-jwt-token-with-jwt-id-claim
            if data.temp_access:
                cust: Password = session.query(Password).filter(
                    Password.customer_id == data.customer_id).first()
                token_uuid = jwt.get_unverified_header(token)['kid']
                if not check_hash(
                        str(data.customer_id) + cust.user_pass +
                        str(data.iat) + token_uuid, data.signature):
                    return jsonify({
                        'message':
                        'Token is invalid as you changed password'
                    }), 401

            if f.__name__ != 'reset_with_token' and data.temp_access:
                return jsonify(
                    {'message':
                     'Token does not have access to this method!'}), 401
            return f(data, *args, **kwargs)
Ejemplo n.º 6
0
def callback(ch, method, properties, body):
    data: InputJson = InputJson(**json.loads(body))
    print(" [x] Received %r" % body)
    # Update balances of customers, on average below code takes 0.46 sec
    # Source: https://stackoverflow.com/questions/54365873/sqlalchemy-update-multiple-rows-in-one-transaction
    bal_ = getattr(Balance, data.currency)
    session.query(Balance).filter(
        Balance.customer_id.in_([
            data.customer_id, data.customer_id_to
        ])).update(
            {
                bal_:
                case(
                    {
                        data.customer_id:
                        bal_ - data.amount,  # getattr(Balance, data.currency)
                        data.customer_id_to: bal_ + data.amount
                    },
                    value=Balance.customer_id)
            },
            synchronize_session=False)
    # Commented another method which first of all does Select and then inside Python changes values and then updates
    # values. On average below code takes 0.76 sec
    """
    new_bal: List[Balance] = session.query(Balance).filter(
        (Balance.customer_id == data.customer_id) | (Balance.customer_id == customer_id_to)).all()
    for bal in new_bal:
        if bal.customer_id == data.customer_id:
            setattr(bal, currency, getattr(bal, currency) - amount)
        else:
            setattr(bal, currency, getattr(bal, currency) + amount)
    """

    # Create transaction and add it to Transactions table
    new_transaction = Transaction(customer_id_from=data.customer_id,
                                  customer_id_to=data.customer_id_to,
                                  **{data.currency: data.amount})
    session.add_all([new_transaction])
    session.commit()

    ch.basic_ack(
        delivery_tag=method.delivery_tag
    )  # Answer to RabbitMQ that all is successful => Message is marked as acknowledged
Ejemplo n.º 7
0
def get_me(data: TokenData):
    custs: List[Customer] = session.query(Customer).filter(Customer.id == data.customer_id)
    results = [
        {
            "first_name": cust.first_name,
            "second_name": cust.second_name,
            "join_date": cust.join_date
        } for cust in custs]

    return jsonify({"count": len(results), "custs": results}), 200
Ejemplo n.º 8
0
def get_all_custs(data: TokenData):
    # custs = session.query(Customer).filter(Customer.first_name == 'Dmitry')
    custs = session.query(Customer)
    results = [
        {
            "first_name": cust.first_name,
            "second_name": cust.second_name,
            "join_date": cust.join_date
        } for cust in custs]

    return jsonify({"count": len(results), "custs": results}), 200
Ejemplo n.º 9
0
def delete_user(data: TokenData):
    if not request.args.get('customer_id', type=int):
        return jsonify({'message': 'Not valid request!'}), 400
    if data.access_type != 1:
        return jsonify({'resp': "You don't have rights for this!"}), 400
    customer_id: int = request.args.get('customer_id')
    rowcount = session.query(Customer).filter(Customer.id == customer_id).delete()
    session.commit()
    if rowcount > 0:
        return jsonify({'resp': 'User removed!'}), 200
    else:
        return jsonify({'resp': 'Not found such user!'}), 400
Ejemplo n.º 10
0
def get_trans(data: TokenData):
    transactions: List[Transaction] = session.query(Transaction).filter(
        (Transaction.customer_id_to == data.customer_id) | (Transaction.customer_id_from == data.customer_id)).all()
    results = [
        {'customer_id_from': trans.customer_id_from,
         'customer_id_to': trans.customer_id_to,
         'usd_amt': trans.usd_amt,
         'eur_amt': trans.eur_amt,
         'aed_amt': trans.aed_amt
         }
        for trans in transactions]
    return jsonify({'results': results}), 200
Ejemplo n.º 11
0
def forgot(form):
    """
    Form for Forgot password. It generates one time link to method reset_with_token
    """
    # Check if customer exists in Password table
    cust: Password = session.query(Password).filter(Password.user_email == form.email.data).first()
    if cust:
        token: str = get_token(cust.user_email, cust.customer_id, cust.user_pass, temp_access=True)
        recover_url = url_for(
            'reset_with_token',
            token=token,
            _external=True)
        return jsonify({'recover_link': recover_url}), 200
    else:
        error: str = 'User not found!'
        return render_template('mainpage.html', message=error), 401
Ejemplo n.º 12
0
def auth(form):
    """
    Auth method. Called if previous token has expired. Checks that user exist in DB and password matches and creates
    new token
    """
    cust_pass: Password = session.query(Password).filter(Password.user_email == form.email.data).join(Customer,
                                                                                                      isouter=True).first()
    if not cust_pass:
        error = 'Invalid Credentials. User not found. Please try again.'
        return render_template('mainpage.html', message=error), 401
    if not check_hash(form.password.data, cust_pass.user_pass):
        error = 'Invalid Credentials. Please try again.'
        return render_template('mainpage.html', message=error), 401

    return jsonify(
        {'token': get_token(cust_pass.user_email, cust_pass.customer_id, form.password.data,
                            cust_pass.customer.access_type,
                            temp_access=False).decode('utf-8')}), 200
Ejemplo n.º 13
0
def do_transaction(data: TokenData):
    params: TransactionSchema = TransactionSchema(request.args)
    if not params.validate():
        return jsonify({'message': 'Not valid arguments!'}), 400

    # Get parameters from args
    amount: float = params.amount.data
    currency: str = f'{params.currency.data.lower()}_amt'

    # Check if customer has enough balance
    balance: Balance = session.query(Balance).filter(Balance.customer_id == data.customer_id).first()
    if getattr(balance, currency) < amount:
        return jsonify({'message': 'Not enough money on your balance!'}), 400

    # Publish message to RabbitMQ:
    publish_message({'customer_id': data.customer_id,
                     'customer_id_to': params.customer_id_to.data,
                     'amount': amount,
                     'currency': currency}, queue='transactions')

    return jsonify({'message': 'Transaction made!'}), 200
Ejemplo n.º 14
0
def my_bal(data: TokenData):
    balance: Balance = session.query(Balance).filter(Balance.customer_id == data.customer_id).first()
    results: dict = {'aed_amt': balance.aed_amt, 'usd_amt': balance.usd_amt, 'eur_amt': balance.eur_amt}
    return jsonify(results), 200
Ejemplo n.º 15
0
 def validate_customer_id_to(self, customer_id_to):
     if not session.query(Customer).filter(
             Customer.id == customer_id_to.data).first():
         raise ValidationError('User does not exist!')
Ejemplo n.º 16
0
 def validate_email(self, email):
     if session.query(Password).filter(
             Password.user_email == email.data).first():
         raise ValidationError('User alredy exists!')