-
Notifications
You must be signed in to change notification settings - Fork 8
Commit v0.30
kwmccabe edited this page Apr 17, 2018
·
7 revisions
v0.30 - API Module: Token-Based Auth, upgrade /api/item and /api/user
- +14 -5 [M] web/app/api/authentication.py
- +26 -3 [M] web/app/api/item.py
- +26 -3 [M] web/app/api/user.py
- +4 -4 [M] web/app/item/models.py
- +22 -4 [M] web/app/user/models.py
- Extend
verify_password()
to callUserModel.verify_auth_token(login)
ifpassword
is empty. - Create route
/token
to return 1-hour authorization tokens.
-from flask import g
+from flask import g, jsonify
...
@auth.verify_password
-def verify_password(email,password):
- if not email:
+def verify_password(login,password):
+ if not login:
return False
- user = UserModel.query.filter_by(user_email=email).first()
+ if not password:
+ g.current_user = UserModel.verify_auth_token(login)
+ g.token_used = True
+ return g.current_user is not None
+ user = UserModel.query.filter_by(user_email=login).first()
if not user:
return False
g.current_user = user
+ g.token_used = False
return user.verify_password(password)
...
+@api.route('/token')
+def get_auth_token():
+ if g.token_used:
+ return unauthorized('Invalid Credentials')
+ return jsonify({'token': g.current_user.generate_auth_token(3600).decode('utf-8'), 'expires': 3600})
- Base route
/api/item/
returns items owned by thecurrent_user
. - New route
/api/item/list/
returns all items, regardless ofowner
. - New routes
/api/item/<int:id>/owner/
and/api/item/<int:id>/editor/
return the item's related users.
-from flask import jsonify
+from flask import g, jsonify
from .. import db
from ..item.models import ItemModel
+from ..user.models import UserModel
from . import api
...
-def get_items():
+def get_profile_items():
+ user = UserModel.query.get_or_404( g.current_user.id )
+ return jsonify({ 'item': [item.to_json() for item in user.items] })
+
+@api.route('/item/count/')
+def get_item_count():
+ cnt = db.session.query(ItemModel).count()
+ return jsonify({ 'item': cnt })
+
+@api.route('/item/list/')
+def get_item_list():
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())
+ return jsonify({ 'item': [item.to_json()] })
+
+@api.route('/item/<int:id>/owner/')
+def get_item_owner(id):
+ item = ItemModel.query.get_or_404(id)
+ #return jsonify(item.owner.to_json())
+ return jsonify({ 'user': [item.owner.to_json()] })
+
+@api.route('/item/<int:id>/editor/')
+def get_item_editor(id):
+ item = ItemModel.query.get_or_404(id)
+ return jsonify({ 'user': [iu.user.to_json() for iu in item.item_users] })
- Base route
/api/user/
returns thecurrent_user
. - New route
/api/user/list/
returns all users. - New route
/api/user/<int:id>/item/owner/
returns items owned by this user. - New route
/api/user/<int:id>/item/editor/
returns items editable by this user.
-from flask import jsonify
+from flask import g, jsonify
from .. import db
+from ..item.models import ItemModel
from ..user.models import UserModel
from . import api
@api.route('/user/')
-def get_users():
+def get_profile():
+ user = UserModel.query.get_or_404( g.current_user.id )
+ return jsonify({ 'user': [user.to_json()] })
+
+@api.route('/user/count/')
+def get_user_count():
+ cnt = db.session.query(UserModel).count()
+ return jsonify({ 'user': cnt })
+
+@api.route('/user/list/')
+def get_user_list():
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())
+ return jsonify({ 'user': [user.to_json()] })
+
+@api.route('/user/<int:id>/item/')
+@api.route('/user/<int:id>/item/owner/')
+def get_user_item_owner(id):
+ user = UserModel.query.get_or_404(id)
+ return jsonify({ 'item': [item.to_json() for item in user.items] })
+
+@api.route('/user/<int:id>/item/editor/')
+def get_user_item_editor(id):
+ user = UserModel.query.get_or_404(id)
+ return jsonify({ 'item': [iu.item.to_json() for iu in user.user_items] })
+
- Return absolute paths in JSON urls via the
_external=True
option tourl_for()
.
def to_json(self):
json_item = {
- 'url': url_for('api.get_item', id=self.id),
+ 'url': url_for('api.get_item', id=self.id, _external=True),
...
- 'owner_url': url_for('api.get_user', id=self.owner_id),
+ 'url_owner' : url_for('api.get_item_owner', id=self.id, _external=True),
'owner_id' : self.owner_id,
- #'users_url': url_for('api.get_item_users', id=self.id),
- 'users_count': len(self.item_users)
+ 'url_editor': url_for('api.get_item_editor', id=self.id, _external=True),
+ 'editor_id' : [iu.user_id for iu in self.item_users]
}
return json_item
- Create method
generate_auth_token()
usingTimedJSONWebSignatureSerializer
. - Create reciprocal method
verify_auth_token()
. - Return absolute paths in JSON urls via the
_external=True
option tourl_for()
.
import logging
-from flask import url_for
+from flask import current_app, url_for
from datetime import datetime
+from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from werkzeug.security import generate_password_hash, check_password_hash
...
+ def generate_auth_token(self, expires):
+ logging.debug( "generate_auth_token(%s)" % expires)
+ s = Serializer(current_app.config['SECRET_KEY'],expires_in=expires)
+ return s.dumps({'id': self.id})
+
+ @staticmethod
+ def verify_auth_token(token):
+ s = Serializer(current_app.config['SECRET_KEY'])
+ try:
+ data = s.loads(token)
+ except:
+ return None
+ return UserModel.query.get(data['id'])
...
def to_json(self):
json_user = {
- 'url': url_for('api.get_user', id=self.id),
+ 'url': url_for('api.get_user', id=self.id, _external=True),
...
- #'items_url': url_for('api.get_user_items', id=self.id),
- 'items_count': len(self.user_items)
+ 'url_item_owner' : url_for('api.get_user_item_owner', id=self.id, _external=True),
+ 'count_item_owner' : len(self.items),
+ 'url_item_editor' : url_for('api.get_user_item_editor', id=self.id, _external=True),
+ 'count_item_editor': len(self.user_items)
}
return json_user
Commit-v0.29 | Commit-v0.30 | Commit-v0.31
- 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