|
| 1 | +from flask import Flask, jsonify |
| 2 | +from flask_restful import Api |
| 3 | +from flask_jwt_extended import JWTManager |
| 4 | + |
| 5 | +from resources.refresh_token import TokenRefresh |
| 6 | +from resources.user import UserRegister, UserLogin, UserFreshLogin |
| 7 | +from resources.item import Item, ItemList |
| 8 | +from resources.store import Store, StoreList |
| 9 | + |
| 10 | +app = Flask(__name__) |
| 11 | +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db' |
| 12 | +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
| 13 | +api = Api(app) |
| 14 | +""" |
| 15 | +JWT related configurations began. The following functions includes: |
| 16 | +1) add claims to each jwt |
| 17 | +2) customize the token expired error message |
| 18 | +""" |
| 19 | +app.config['JWT_SECRET_KEY'] = 'super-secret' |
| 20 | +app.config['JWT_BLACKLIST_ENABLED'] = True # enable blacklist feature |
| 21 | +app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access', 'refresh'] # allow blacklisting for access and refresh tokens |
| 22 | +jwt = JWTManager(app) |
| 23 | + |
| 24 | +""" |
| 25 | +claims are data we choose to attached to each jwt payload |
| 26 | +and for each jwt protected endpoint, we can retrieve these claims via `get_jwt_claims()` |
| 27 | +one possible use case for claims are access level control, which is shown below |
| 28 | +""" |
| 29 | + |
| 30 | + |
| 31 | +@jwt.user_claims_loader |
| 32 | +def add_claims_to_jwt(identity): |
| 33 | + if identity == 1: |
| 34 | + return {'isAdmin': True} |
| 35 | + return {'isAdmin': False} |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | +black_list = [2, 4, 6] # user.id that are black listed |
| 40 | + |
| 41 | + |
| 42 | +# this method will check if a token is blacklisted, and will be called automatically when blacklist is enabled |
| 43 | +@jwt.token_in_blacklist_loader |
| 44 | +def check_if_token_in_blacklist(decrypted_token): |
| 45 | + return decrypted_token['identity'] in black_list |
| 46 | + |
| 47 | + |
| 48 | +# the following callbacks are used for customizing jwt response/error messages |
| 49 | +@jwt.expired_token_loader |
| 50 | +def expired_token_callback(): |
| 51 | + return jsonify({ |
| 52 | + 'message': 'The token has expired.', |
| 53 | + 'error': 'token_expired' |
| 54 | + }), 401 |
| 55 | + |
| 56 | + |
| 57 | +@jwt.invalid_token_loader |
| 58 | +def invalid_token_callback(error): |
| 59 | + return jsonify({ |
| 60 | + 'message': 'Signature verification failed.', |
| 61 | + 'error': 'invalid_token' |
| 62 | + }), 401 |
| 63 | + |
| 64 | + |
| 65 | +@jwt.unauthorized_loader |
| 66 | +def missing_token_callback(error): |
| 67 | + return jsonify({ |
| 68 | + "description": "Request does not contain an access token.", |
| 69 | + 'error': 'authorization_required' |
| 70 | + }), 401 |
| 71 | + |
| 72 | + |
| 73 | +@jwt.needs_fresh_token_loader |
| 74 | +def token_not_fresh_callback(): |
| 75 | + return jsonify({ |
| 76 | + "description": "The token is not fresh.", |
| 77 | + 'error': 'fresh_token_required' |
| 78 | + }), 401 |
| 79 | + |
| 80 | + |
| 81 | +@jwt.revoked_token_loader |
| 82 | +def revoked_token_callback(): |
| 83 | + return jsonify({ |
| 84 | + "description": "The token has been revoked.", |
| 85 | + 'error': 'token_revoked' |
| 86 | + }), 401 |
| 87 | + |
| 88 | +# JWT configuration ends ################################### |
| 89 | + |
| 90 | + |
| 91 | +@app.before_first_request |
| 92 | +def create_tables(): |
| 93 | + db.create_all() |
| 94 | + |
| 95 | +api.add_resource(TokenRefresh, '/refresh') |
| 96 | +api.add_resource(Store, '/store/<string:name>') |
| 97 | +api.add_resource(StoreList, '/stores') |
| 98 | +api.add_resource(Item, '/item/<string:name>') |
| 99 | +api.add_resource(ItemList, '/items') |
| 100 | +api.add_resource(UserRegister, '/register') |
| 101 | +api.add_resource(UserLogin, '/login') |
| 102 | +api.add_resource(UserFreshLogin, '/fresh_login') |
| 103 | + |
| 104 | +if __name__ == '__main__': |
| 105 | + from db import db |
| 106 | + |
| 107 | + db.init_app(app) |
| 108 | + app.run(port=5000, debug=True) |
0 commit comments