-
Notifications
You must be signed in to change notification settings - Fork 8
Commit v0.29
kwmccabe edited this page Apr 17, 2018
·
7 revisions
v0.29 - 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
authentication
anderrors
for access control. - Import
item
anduser
for 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_password
and@auth.error_handler
decorators. -
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()
+
+@auth.verify_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)
+
+
+@auth.error_handler
+def auth_error():
+ return unauthorized('Invalid Credentials')
+
+
+@api.before_request
+@auth.login_required
+def before_request():
+ if not g.current_user.active:
+ return forbidden('Inactive Account')
- Generate JSON responses for
unauthorized
andforbidden
errors.
+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
+
+
+@api.route('/item/')
+def get_items():
+ rows = db.session.query(ItemModel)
+ return jsonify({ 'item': [item.to_json() for item in rows] })
+
+@api.route('/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
+
+
+@api.route('/user/')
+def get_users():
+ rows = db.session.query(UserModel)
+ return jsonify({ 'user': [user.to_json() for user in rows] })
+
+@api.route('/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-HTTPAuth
topip
install.
Flask-Bootstrap==3.3.7.1
+Flask-HTTPAuth==3.2.3
Flask-Login==0.4.1
Commit-v0.28 | Commit-v0.29 | Commit-v0.30
- 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