-
Notifications
You must be signed in to change notification settings - Fork 8
Commit v0.29
kwmccabe edited this page Apr 11, 2018
·
7 revisions
API module, Flask-HTTPAuth
- +3 -0 [M] web/app/init.py
- +5 -0 [A] web/app/api/init.py
- +31 -0 [A] web/app/api/authentication.py
- +18 -0 [A] web/app/api/errors.py
- +15 -0 [A] web/app/api/item.py
- +15 -0 [A] web/app/api/user.py
- +3 -3 [M] web/app/item/models.py
- +3 -2 [M] web/app/item/views.py
- +2 -2 [M] web/app/user/models.py
- +8 -1 [M] web/flaskapp.py
- +1 -0 [M] web/requirements.txt
- Register API module with Flask Blueprint.
- All API routes begin with
/api.
+ from .api import api as api_blueprint
+ app.register_blueprint(api_blueprint, url_prefix='/api')
- Initialize API module.
- Import
authenticationanderrorsfor access control. - Import
itemanduserfor output routes.
+from flask import Blueprint
+
+api = Blueprint('api', __name__, template_folder='templates')
+
+from . import authentication, errors, item, user
- Initialize
HTTPBasicAuth, scoped within the API module. - Provide methods for
@auth.verify_passwordand@auth.error_handlerdecorators. -
verify_password()leverages the existingverify_password()method inUserModel. -
auth_error()calls theunauthorized()method inerrors.py. -
before_request()checks that current user exists and is active, or calls theforbidden()method inerrors.py.
+from flask import g
+from flask_httpauth import HTTPBasicAuth
+from ..user.models import UserModel
+from . import api
+from .errors import forbidden, unauthorized
+
+auth = HTTPBasicAuth()
+
[email protected]_password
+def verify_password(email,password):
+ if not email:
+ return False
+ user = UserModel.query.filter_by(user_email=email).first()
+ if not user:
+ return False
+ g.current_user = user
+ return user.verify_password(password)
+
+
[email protected]_handler
+def auth_error():
+ return unauthorized('Invalid Credentials')
+
+
[email protected]_request
[email protected]_required
+def before_request():
+ if not g.current_user.active:
+ return forbidden('Inactive Account')
- Generate JSON responses for
unauthorizedandforbiddenerrors.
+from flask import jsonify, request
+
+def unauthorized(message):
+ response = jsonify({ \
+ 'code': 401, 'name': 'Unauthorized', 'message': message, 'url': request.url \
+ #, 'request': dir(request) \
+ })
+ response.status_code = 401
+ return response
+
+def forbidden(message):
+ response = jsonify({ \
+ 'code': 403, 'name': 'Forbidden', 'message': message, 'url': request.url \
+ #, 'request': dir(request) \
+ })
+ response.status_code = 403
+ return response
- Create route
/item/to return all items in JSON format. - Create route
/item/<int:id>/to return single item in JSON format.
+from flask import jsonify
+from .. import db
+from ..item.models import ItemModel
+from . import api
+
+
[email protected]('/item/')
+def get_items():
+ rows = db.session.query(ItemModel)
+ return jsonify({ 'item': [item.to_json() for item in rows] })
+
[email protected]('/item/<int:id>/')
+def get_item(id):
+ item = ItemModel.query.get_or_404(id)
+ return jsonify(item.to_json())
- Create route
/user/to return all users in JSON format. - Create route
/user/<int:id>/to return single user in JSON format.
+from flask import jsonify
+from .. import db
+from ..user.models import UserModel
+from . import api
+
+
[email protected]('/user/')
+def get_users():
+ rows = db.session.query(UserModel)
+ return jsonify({ 'user': [user.to_json() for user in rows] })
+
[email protected]('/user/<int:id>/')
+def get_user(id):
+ user = UserModel.query.get_or_404(id)
+ return jsonify(user.to_json())
- Activate some API urls within
to_json().
def to_json(self):
json_item = {
- #'url': url_for('api.get_item', id=self.id),
+ 'url': url_for('api.get_item', id=self.id),
...
- #'owner_url': url_for('api.get_user', id=self.owner_id),
+ 'owner_url': url_for('api.get_user', id=self.owner_id),
'owner_id' : self.owner_id,
#'users_url': url_for('api.get_item_users', id=self.id),
- 'users_count': self.item_users.count()
+ 'users_count': len(self.item_users)
}
return json_item
from flask_login import current_user, login_required
from jinja2 import TemplateNotFound
from .. import db, flash_errors
+from ..decorators import get_list_opts
+from ..user.models import UserModel
from . import item
from .models import ItemModel, ItemUserModel, get_owner_id_choices
-from ..user.models import UserModel
from .forms import CreatItemForm, EditItemForm
-from ..decorators import get_list_opts
- Activate some API urls within
to_json().
def to_json(self):
json_user = {
- #'url': url_for('api.get_user', id=self.id),
+ 'url': url_for('api.get_user', id=self.id),
...
#'items_url': url_for('api.get_user_items', id=self.id),
- 'items_count': self.user_items.count()
+ 'items_count': len(self.user_items)
- Update the
page_not_found()function to return JSON for bad API requests.
-from flask import current_app, flash, render_template
+from flask import current_app, flash, jsonify, render_template, request
...
# Page Not Found
@app.errorhandler(404)
def page_not_found(e):
+ if request.accept_mimetypes.accept_json and not request.accept_mimetypes.accept_html:
+ response = jsonify({ \
+ 'code': e.code, 'name': e.name, 'message': e.description, 'url': request.url \
+ #, 'error': dir(e), 'request': dir(request) \
+ })
+ response.status_code = 404
+ return response
return render_template('404.html', error=e), 404
- Add
Flask-HTTPAuthtopipinstall.
Flask-Bootstrap==3.3.7.1
+Flask-HTTPAuth==3.2.3
Flask-Login==0.4.1
- FlaskApp Tutorial
- Table of Contents
- About
- Application Setup
- Modules, Templates, and Layouts
- Database Items, Forms, and CRUD
- List Filter, Sort, and Paginate
- Users and Login
- Database Relationships
- API Module, HTTPAuth and JSON
- Refactoring User Roles and Item Status
- AJAX and Public Pages