Ejemplo n.º 1
0
def add_user(user_email: str, user_pass: str) -> Tuple[int, str]:
    """
    Add new user to DB
    :param user_email: str, user's email address
    :param user_pass: str, user hashed password
    :return:
    """
    hashed_pass: str = get_hash(user_pass)
    # ADD to DB new customer
    new_cust: Customer = Customer(first_name='New_user',
                                  second_name='flask_August',
                                  nickname_telegram='@test',
                                  access_type=0,
                                  join_date=datetime.datetime.utcnow())
    # ADD new bal to user
    new_bal: Balance = Balance(customer=new_cust,
                               usd_amt=0,
                               eur_amt=0,
                               aed_amt=0)
    # ADD new password
    new_pass: Password = Password(customer=new_cust,
                                  user_email=user_email,
                                  user_pass=hashed_pass)
    # add_all is similar to git add ...
    session.add_all([new_cust])
    # flush is similar to git commit ...
    session.flush()
    # commit is similar to git push ...
    session.commit()

    return new_cust.id, hashed_pass
Ejemplo n.º 2
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.º 3
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.º 4
0
def get_token(user_email: str,
              customer_id: int,
              hashed_pass: str,
              access_type: int = 0,
              temp_access: bool = False) -> str:
    """
    Function generates jwt token. Payload - user_email, creation date of token and exp date
    Header - uuid of Token
    Signature - encoded with private key signature
    :param access_type: int, 0 - normal access, 1 - admin
    :param customer_id: int, customer unique identifier in DB
    :param hashed_pass: str, hashed password of customer
    :param temp_access: bool, either it is token for reset or not
    :param user_email: str, email of customer/user
    :return: token: str, generated token
    """
    creation_date: datetime = datetime.datetime.utcnow()
    exp_date: datetime = datetime.datetime.utcnow() + datetime.timedelta(
        days=3)
    token_uuid: str = uuid.uuid4().hex

    # 'signature' is parameter in payload equals to hash(customer_id + user_pass_hash + creation_date + token_uuid)
    # The purpose of signature is: once user changes password => hash changes and signature won't match => all tokens will be revoked
    # Source: https://security.stackexchange.com/questions/153746/one-time-jwt-token-with-jwt-id-claim
    signature: str = get_hash(
        str(customer_id) + hashed_pass +
        str(timegm(creation_date.utctimetuple())) + token_uuid)

    # 'temp_access' parameter for forgot password
    token = jwt.encode(payload={
        'user_email': user_email,
        'customer_id': customer_id,
        'access_type': access_type,
        'temp_access': temp_access,
        'exp': exp_date,
        'iat': creation_date,
        'signature': signature
    },
                       headers={'kid': token_uuid},
                       key=PRIVATE_KEY,
                       algorithm=ALG)
    # Add token to DB
    new_token: Token = Token(customer_id=customer_id,
                             token_uuid=token_uuid,
                             creation_date=creation_date,
                             exp_date=exp_date)
    session.add_all([new_token])
    session.flush()
    session.commit()
    return token
Ejemplo n.º 5
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.º 6
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.º 7
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