Giter Site home page Giter Site logo

miguelgrinberg / rest-auth Goto Github PK

View Code? Open in Web Editor NEW
915.0 37.0 335.0 15 KB

Example application for my RESTful Authentication with Flask article.

Home Page: http://blog.miguelgrinberg.com/post/restful-authentication-with-flask

License: MIT License

Python 100.00%

rest-auth's Introduction

REST-auth

Companion application to my RESTful Authentication with Flask article.

Installation

After cloning, create a virtual environment and install the requirements. For Linux and Mac users:

$ virtualenv venv
$ source venv/bin/activate
(venv) $ pip install -r requirements.txt

If you are on Windows, then use the following commands instead:

$ virtualenv venv
$ venv\Scripts\activate
(venv) $ pip install -r requirements.txt

Running

To run the server use the following command:

(venv) $ python api.py
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader

Then from a different terminal window you can send requests.

API Documentation

  • POST /api/users

    Register a new user.
    The body must contain a JSON object that defines username and password fields.
    On success a status code 201 is returned. The body of the response contains a JSON object with the newly added user. A Location header contains the URI of the new user.
    On failure status code 400 (bad request) is returned.
    Notes:

    • The password is hashed before it is stored in the database. Once hashed, the original password is discarded.
    • In a production deployment secure HTTP must be used to protect the password in transit.
  • GET /api/users/<int:id>

    Return a user.
    On success a status code 200 is returned. The body of the response contains a JSON object with the requested user.
    On failure status code 400 (bad request) is returned.

  • GET /api/token

    Return an authentication token.
    This request must be authenticated using a HTTP Basic Authentication header.
    On success a JSON object is returned with a field token set to the authentication token for the user and a field duration set to the (approximate) number of seconds the token is valid.
    On failure status code 401 (unauthorized) is returned.

  • GET /api/resource

    Return a protected resource.
    This request must be authenticated using a HTTP Basic Authentication header. Instead of username and password, the client can provide a valid authentication token in the username field. If using an authentication token the password field is not used and can be set to any value.
    On success a JSON object with data for the authenticated user is returned.
    On failure status code 401 (unauthorized) is returned.

Example

The following curl command registers a new user with username miguel and password python:

$ curl -i -X POST -H "Content-Type: application/json" -d '{"username":"miguel","password":"python"}' http://127.0.0.1:5000/api/users
HTTP/1.0 201 CREATED
Content-Type: application/json
Content-Length: 27
Location: http://127.0.0.1:5000/api/users/1
Server: Werkzeug/0.9.4 Python/2.7.3
Date: Thu, 28 Nov 2013 19:56:39 GMT

{
  "username": "miguel"
}

These credentials can now be used to access protected resources:

$ curl -u miguel:python -i -X GET http://127.0.0.1:5000/api/resource
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 30
Server: Werkzeug/0.9.4 Python/2.7.3
Date: Thu, 28 Nov 2013 20:02:25 GMT

{
  "data": "Hello, miguel!"
}

Using the wrong credentials the request is refused:

$ curl -u miguel:ruby -i -X GET http://127.0.0.1:5000/api/resource
HTTP/1.0 401 UNAUTHORIZED
Content-Type: text/html; charset=utf-8
Content-Length: 19
WWW-Authenticate: Basic realm="Authentication Required"
Server: Werkzeug/0.9.4 Python/2.7.3
Date: Thu, 28 Nov 2013 20:03:18 GMT

Unauthorized Access

Finally, to avoid sending username and password with every request an authentication token can be requested:

$ curl -u miguel:python -i -X GET http://127.0.0.1:5000/api/token
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 139
Server: Werkzeug/0.9.4 Python/2.7.3
Date: Thu, 28 Nov 2013 20:04:15 GMT

{
  "duration": 600,
  "token": "eyJhbGciOiJIUzI1NiIsImV4cCI6MTM4NTY2OTY1NSwiaWF0IjoxMzg1NjY5MDU1fQ.eyJpZCI6MX0.XbOEFJkhjHJ5uRINh2JA1BPzXjSohKYDRT472wGOvjc"
}

And now during the token validity period there is no need to send username and password to authenticate anymore:

$ curl -u eyJhbGciOiJIUzI1NiIsImV4cCI6MTM4NTY2OTY1NSwiaWF0IjoxMzg1NjY5MDU1fQ.eyJpZCI6MX0.XbOEFJkhjHJ5uRINh2JA1BPzXjSohKYDRT472wGOvjc:x -i -X GET http://127.0.0.1:5000/api/resource
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 30
Server: Werkzeug/0.9.4 Python/2.7.3
Date: Thu, 28 Nov 2013 20:05:08 GMT

{
  "data": "Hello, miguel!"
}

Once the token expires it cannot be used anymore and the client needs to request a new one. Note that in this last example the password is arbitrarily set to x, since the password isn't used for token authentication.

An interesting side effect of this implementation is that it is possible to use an unexpired token as authentication to request a new token that extends the expiration time. This effectively allows the client to change from one token to the next and never need to send username and password after the initial token was obtained.

Change Log

v0.3 - Return token duration.

v0.2 - Return a 201 status code and Location header from /api/users endpoint.

v0.1 - Initial release.

rest-auth's People

Contributors

chaynsaw avatar dealenx avatar dependabot[bot] avatar floweb avatar marioneubert avatar miguelgrinberg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rest-auth's Issues

HttpBasicAuth seems to fail being deployed to heroku

Hi, Miguel! I forked the repo, switched from sqlite to MySQL and deployed it on heroku, but I get 401 on the protected endpoints.

$ curl -u miguel:python -i -X GET https://apisrv.herokuapp.com/api/resource
HTTP/1.1 401 UNAUTHORIZED
Connection: keep-alive
Server: gunicorn/20.0.4
Date: Sun, 14 Jun 2020 14:04:59 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 19
Www-Authenticate: Basic realm="Authentication Required"
Via: 1.1 vegur

Unauthorized Access

$ curl -u miguel:python -i -X GET https://apisrv.herokuapp.com/api/token
HTTP/1.1 401 UNAUTHORIZED
Connection: keep-alive
Server: gunicorn/20.0.4
Date: Sun, 14 Jun 2020 14:05:29 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 19
Www-Authenticate: Basic realm="Authentication Required"
Via: 1.1 vegur

Unauthorized Access

I tested the code in virtualenv and it worked great.

My forked repo is https://github.com/fung1/REST-auth

404 Not found

hello, i have installed the code using your way,all the procedure are successful ,but,when i run python api.py,and click the http://127.0.0.1:5000/ ,the web was not found,could you tell me how to solve the problem? thanks

Include docker + nginx for completion

To complete this example one could include a Dockerfile, docker-compose file and nginx config to demonstrate the whole pipeline. I have something drafted and be willing to share if you think this would be in the scope of this repository.

How to secure Flask API resource using Google OAuth2

Hi Miguel,
Thanks for your article. I am trying to develop flask app which serves as API to my front end vue.js application. Now i want to secure my API resources and also i want to keep track of user like who register using the Oauth2. I am only keeping google as option so that i can get the email address i can store in DB.

Now google token expires in 1 hour and i want some help in order design this mapping how do i auto refresh token if it expires without prompting user give google sign page.

My requirements are as following:

  • What is best way to refresh token either stored in DB and then check with google see if it is expired then update it.

  • when user hit on login url i want to make sure if user has logged in earlier it should pick up his/her token from DB and refresh it if needed.

  • How do i secure my API resource since i am not using Flask-Login ext.

  • How do i test my API using postman since Oauth for google is challenging in postman.

  • What is best with your expertise to keep auth part in vue.js app or is there way i can extend my auth from flask to vue.js so i don't have to re code it again.

Right now i am having following approach which is buggy and breaks sometimes and its still in testing phase.

Please suggest me your best approach and thank you very much for your time and feedback.

auth.py file code

from app import app, db
from flask import session, make_response,current_app, render_template, flash, redirect, url_for, request, jsonify, g, current_app
from forms import LoginForm, RegistrationForm, EditProfileForm
from flask_login import current_user, login_user, logout_user, login_required
from app.models.Users_model import User
from flask_login import login_user, logout_user, current_user, login_required, UserMixin
from requests_oauthlib import OAuth2Session
from requests.exceptions import HTTPError
import json
from flask_httpauth import HTTPBasicAuth
from app.auth import bp
import requests
from flask.json import jsonify
from time import time


# This decorator function witll implement login method
@bp.route('/login', methods=['GET', 'POST'])
def login():
    #If we don't have session token or email session token then user needs to sign in
    if session.get('oauth_token') is None:
        print session.get('oauth_token')
        session.permanent = True
        client_id = current_app.config['OAUTH_CREDENTIALS_GOOGLE_ID']
        scope = current_app.config['SCOPE']
        redirect_uri = current_app.config['REDIRECT_URI']
        authorization_base_url = current_app.config['AUTHORISATION_BASE_URL']
        google = OAuth2Session(client_id, scope=scope, redirect_uri=redirect_uri)
        authorization_url, state = google.authorization_url(authorization_base_url, access_type="offline",
                                                            approval_prompt="force")
        session['oauth_state'] = state
        return redirect(authorization_url)
    #here if user has session token then we need to validate that session token with db stored token
    else:
        print session['oauth_state']
        print session['oauth_token']
        print session['email_id']
        AccesssToken = session['oauth_token']['access_token']
        RefreshToken = session['oauth_token']['refresh_token']
        print AccesssToken
        print RefreshToken
        user = User.query.filter_by(email=session['email_id']).first()
        if user:
            validate_url = ('https://www.googleapis.com/oauth2/v1/tokeninfo?'
                            'access_token=%s' % user.auth_token)
            valid_user =requests.get(validate_url).json()
            #Now here if auth token is not valid which will return no result in calling that API. redirect to refresh token.
            if 'error' in valid_user:
                return redirect(url_for('auth.refresh_token'))

            #if token is valid then we will redirect user as logged in and then send them to main page.
            else:
                print valid_user
                print valid_user['email']
                print valid_user['expires_in']
                login_user(user, True)
                return redirect(url_for('main.index'))
        #If user does not exists in DB then we will send user to login page with google login.
        else:
            return redirect(url_for('auth.login'))


# This is callback URL
@bp.route('/callback')
def callback():
    client_id = current_app.config['OAUTH_CREDENTIALS_GOOGLE_ID']
    scope = current_app.config['SCOPE']
    redirect_uri = current_app.config['REDIRECT_URI']
    authorization_base_url = current_app.config['AUTHORISATION_BASE_URL']
    client_secret = current_app.config['OAUTH_CREDENTIALS_GOOGLE_SECRET']
    token_url = current_app.config['TOKEN_URL']

    google = OAuth2Session(client_id, redirect_uri=redirect_uri,state=session['oauth_state'])
    token = google.fetch_token(token_url, client_secret=client_secret,authorization_response=request.url)
    if token is None:
        return render_template('errors/404.html')
    print token
    session['oauth_token'] = token
    user_profile = google.get('https://www.googleapis.com/oauth2/v1/userinfo').json()
    print user_profile
    user = User.query.filter_by(email=user_profile['email']).first()
    print "I am checking for user %s if it is in DB" %user_profile['email']
    session['email_id']=user_profile['email']
    print session['email_id']
    if user:
        return redirect(url_for('auth.validate_authToken'))

    else:
        user = User(nickname=user_profile['given_name'], email=user_profile['email'],
                    auth_token=token['access_token'], refresh_token=token['refresh_token'],
                    expires_in=token['expires_in'])
        db.session.add(user)
        db.session.commit()
        flash('Congratulations, you are now a registered and Logged in!')
        login_user(user, True)
        return redirect(url_for('main.index'))


@bp.route('/validate_authToken', methods=['GET', 'POST'])
def validate_authToken():
    valid_token_session = session['oauth_token']
    print valid_token_session
    user = User.query.filter_by(email=session['email_id']).first()
    valid_token_db = user.auth_token
    ref_token = user.refresh_token
    #Condition to check token stored in DB and session are the same then check if it is valid.
    if valid_token_session['access_token'] == valid_token_db:
        validate_url = ('https://www.googleapis.com/oauth2/v1/tokeninfo?' 'access_token=%s' % valid_token_session)
        validata = jsonify(requests.get(validate_url).json())
        if validata:
            login_user(user, True)
            return redirect(url_for('main.index'))
        #If token becomes invalid we need to refresh it using the below method
        else:
            return redirect(url_for('refresh_token(ref_token)'))

    else:
        validate_data = requests.get('https://www.googleapis.com/oauth2/v1/tokeninfo?' 'access_token=%s' % valid_token_session)
        if validate_data:
            login_user(user, True)
            return redirect(url_for('main.index'))
        else:
            return redirect(url_for('refresh_token(ref_token)'))



#This is decorator function will refresh token
@bp.route('/refresh_token',methods=['GET','POST'])
def refresh_token():
    token = session['oauth_token']
    refresh_url = current_app.config['TOKEN_URL']
    extra = {
        'client_id': current_app.config['OAUTH_CREDENTIALS_GOOGLE_ID'],
        'client_secret': current_app.config['OAUTH_CREDENTIALS_GOOGLE_SECRET'],
        'offline': True
    }
    def token_updater(token):
        session['oauth_token'] = token

    google = OAuth2Session(current_app.config['OAUTH_CREDENTIALS_GOOGLE_ID'],
                           token=token,
                           auto_refresh_kwargs=extra,
                           auto_refresh_url=refresh_url,
                           token_updater=token_updater)
    user_profile = google.get('https://www.googleapis.com/oauth2/v1/userinfo').json()
    #If we get new token just update that token in db and not sure about session if it auto update we need to validate it.
    if user_profile:
        print user_profile
        print session['oauth_token']

        user = User.query.filter_by(email=user_profile['email']).first()
        user.refresh_token=session['oauth_token']['refresh_token'],
        user.auth_token = session['oauth_token']['access_token']
        db.session.commit()
        login_user(user, True)
        return redirect(url_for('main.index'))
    else:
        return redirect(url_for('auth.login'))






# This Decorator function is for creating user
@bp.route('/register', methods=['GET', 'POST'])
def register():
    if current_user.is_authenticated:
        return redirect(url_for('main.index'))
    form = RegistrationForm()
    if form.validate_on_submit():
        user = User(nickname=form.nickname.data, email=form.email.data, mob=int(form.mob.data))
        user.set_password(form.password.data)
        db.session.add(user)
        db.session.commit()
        flash('Congratulations, you are now a registered user!')
        return redirect(url_for('auth.login'))
    return render_template('auth/register.html', title='Register', form=form)


# This decorator function will be for logout
@bp.route('/logout')
def logout():
    logout_user()
    return redirect(url_for('main.index'))

How to test curl POST with token key and data ?

How to test curl POST with token key and data ?
Example:
curl -H "Content-Type: application/json" -H "authToken: eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ4OTk3ODY3MSwiaWF0IjoxNDg5OTc4MDcxfQ.eyJpZCI6MX0.wphF8H3o4p9r-DcynZr_6o_vxOccDaQVfcgQDOsUZrM" -d '{"username":"Test1","password":"adada"}' http://127.0.0.1:5000/api/users
Result:
Unauthorized Access

Could flask be detecting request is coming from a browser and always returning 200 status despite invalid credentials?

Hi,

First of all thank you so much for releasing this. I am using this to authenticate users for my first web app.

When I am making login requests from the command line, python, and node I get 401 status for invalid credentials just as I should. But when i run and test locally in browser I always get 200 for some odd reason. I also cant find anything online about anyone having a similar issue and have tried posting on SO (here) to no avail. Has anyone here had this happen?

Get all users

@app.route('/api/users', methods=['GET'])
def index():
users = User.query.all()
if not users:
abort(400)
return jsonify(users)

Result:

<title>500 Internal Server Error</title>

Internal Server Error

The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.

User can create and use multiple tokens.

Hello.

When using the example to create a token, all is functionnal. But, they may be a bug :
When the user creates a token, he can then use this token to create another token. Then, both tokens can be used to access the protected resource.

Maybe this should not be allowed, and that only the lastly created token can be used.

Cheers.

A security concern.

What doesn't allow someone to sniff the request headers and get the credentials used to get the token ?

A note: even if the password is encrypted, the sniffer ( attacker ) can just grab the hashed password since it is what is decrypted at the server ( it won't matter if the password is encrypted or not is what I mean ).

Unlimited Token Timeout

With this setup, is it possible to set an auth token to never time out? I've tried passing a negative value to see if that would work but it seems unsupported.

A security question regarding get_user

Thank you for a wonderful resource.
This is not as much a technical issue as it is a data protection / logical issue.

What is the purpose of exposing the get_user(id) function as a API-Call?
The risk is that someone could iterate over the ids to get a full list of your users. Even by requiring login you would potentally be able to do the same as a registered user.

As far as I can see you are not needing the user id except to verify that the user has been created in the database.
Wouldn't it be better to have that as a function of the User model, or as part of the new_user function?

My apologies if these are stupid questions.

Unabel to post new user and getting error

E:\tools\apiserver>python authentication.py
C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask_sqlalchemy\__init__.py:839: FSADeprecationWarning: SQLALCHEMY_TRACK_
MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True or False to suppress this warning.
  'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and '
 * Restarting with stat
C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask_sqlalchemy\__init__.py:839: FSADeprecationWarning: SQLALCHEMY_TRACK_
MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True or False to suppress this warning.
  'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and '
 * Debugger is active!
 * Debugger PIN: 257-880-472
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [04/Jan/2018 17:47:27] "POST /api/users HTTP/1.1" 500 -
Traceback (most recent call last):
  File "C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask\app.py", line 1997, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask\app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask\app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask\_compat.py", line 33, in reraise
    raise value
  File "C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask\app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask\_compat.py", line 33, in reraise
    raise value
  File "C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\jeevan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\flask\app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "E:\tools\apiserver\authentication.py", line 65, in new_user
    username = request.json.get('username')
AttributeError: 'NoneType' object has no attribute 'get'

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users

Hi Miguel,

I have tried running your code in the same exact way you displayed it, but I continue getting an error when trying to send POST requests to update the database with a new user (p.s. I use the same exact curl request stated in the README.md).

Find below the error:

File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/flask/app.py", line 1997, in call
return self.wsgi_app(environ, start_response)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functionsrule.endpoint
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/tests.py", line 88, in new_user
if User.query.filter_by(username=username).first() is not None:
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2755, in first
ret = list(self[0:1])
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2547, in getitem
return list(res)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2855, in iter
return self._execute_and_instances(context)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2878, in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 945, in execute
return meth(self, multiparams, params)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 263, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1053, in _execute_clauseelement
compiled_sql, distilled_params
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1189, in _execute_context
context)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1402, in _handle_dbapi_exception
exc_info
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 203, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 186, in reraise
raise value.with_traceback(tb)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1182, in _execute_context
context)
File "/Users/lorenzmaresca/Desktop/Cloud Computing/CCLab/Mini Project/flask_venv/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 470, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users [SQL: 'SELECT users.id AS users_id, users.username AS users_username, users.password_hash AS users_password_hash \nFROM users \nWHERE users.username = ?\n LIMIT ? OFFSET ?'] [parameters: ('kseniya', 1, 0)]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.