33Copyright (c) 2019 - present AppSeed.us
44"""
55
6- from datetime import datetime , timezone
6+ from datetime import datetime , timezone , timedelta
77
8- import json
8+ from functools import wraps
99
1010from flask import request
11- from flask_restx import Api , Resource , fields , abort
12- from flask_jwt_extended import JWTManager , jwt_required , get_jwt , create_access_token , get_jwt_identity
11+ from flask_restx import Api , Resource , fields
12+
13+ import jwt
1314
1415from .models import db , Users , JWTTokenBlocklist
16+ from .config import BaseConfig
1517
1618rest_api = Api (version = "1.0" , title = "Users API" )
17- jwt = JWTManager ()
18-
19- """
20- Helper function for revoking JWT token
21- """
22-
23-
24- @jwt .token_in_blocklist_loader
25- def check_if_token_revoked (jwt_header , jwt_payload ):
26- jti = jwt_payload ["jti" ]
27- token = db .session .query (JWTTokenBlocklist .id ).filter_by (jti = jti ).scalar ()
28- return token is not None
2919
3020
3121"""
@@ -49,6 +39,47 @@ def check_if_token_revoked(jwt_header, jwt_payload):
4939logout_model = rest_api .model ('LogoutModel' , {"token" : fields .String (required = True )})
5040
5141
42+ """
43+ Helper function for JWT token required
44+ """
45+
46+ def token_required (f ):
47+
48+ @wraps (f )
49+ def decorator (* args , ** kwargs ):
50+
51+ token = None
52+
53+ if "authorization" in request .headers :
54+ token = request .headers ["authorization" ]
55+
56+ if not token :
57+ return {"success" : False , "msg" : "Valid JWT token is missing" }, 400
58+
59+ try :
60+ data = jwt .decode (token , BaseConfig .SECRET_KEY , algorithms = ["HS256" ])
61+ current_user = Users .get_by_email (data ["email" ])
62+
63+ if not current_user :
64+ return {"success" : False ,
65+ "msg" : "Sorry. Wrong auth token. This user does not exist." }, 400
66+
67+ token_expired = db .session .query (JWTTokenBlocklist .id ).filter_by (jwt_token = token ).scalar ()
68+
69+ if token_expired is not None :
70+ return {"success" : False , "msg" : "Token revoked." }, 400
71+
72+ if not current_user .check_jwt_auth_active ():
73+ return {"success" : False , "msg" : "Token expired." }, 400
74+
75+ except :
76+ return {"success" : False , "msg" : "Token is invalid" }, 400
77+
78+ return f (current_user , * args , ** kwargs )
79+
80+ return decorator
81+
82+
5283"""
5384 Flask-Restx routes
5485"""
@@ -80,7 +111,7 @@ def post(self):
80111 new_user .save ()
81112
82113 return {"success" : True ,
83- "userID" : new_user .id ,
114+ "userID" : new_user .id ,
84115 "msg" : "The user was successfully registered" }, 200
85116
86117
@@ -109,11 +140,14 @@ def post(self):
109140 "msg" : "Sorry. Wrong credentials." }, 400
110141
111142 # create access token uwing JWT
112- access_token = create_access_token (identity = _email )
143+ token = jwt .encode ({'email' : _email , 'exp' : datetime .utcnow () + timedelta (minutes = 30 )}, BaseConfig .SECRET_KEY )
144+
145+ user_exists .set_jwt_auth_active (True )
146+ user_exists .save ()
113147
114148 return {"success" : True ,
115- "token" : access_token ,
116- "user" : user_exists .toJSON () }, 200
149+ "token" : token ,
150+ "user" : user_exists .toJSON ()}, 200
117151
118152
119153@rest_api .route ('/api/users/edit' )
@@ -123,28 +157,21 @@ class EditUser(Resource):
123157 """
124158
125159 @rest_api .expect (user_edit_model )
126- @jwt_required ()
127- def post (self ):
128-
129- user_email = get_jwt_identity ()
130- current_user = Users .get_by_email (user_email )
131-
132- if not current_user :
133- return {"success" : False ,
134- "msg" : "Sorry. Wrong auth token. This user does not exist." }, 400
160+ @token_required
161+ def post (self , current_user ):
135162
136163 req_data = request .get_json ()
137164
138165 _new_username = req_data .get ("username" )
139166 _new_email = req_data .get ("email" )
140167
141168 if _new_username :
142- current_user .update_username (_new_username )
169+ self .update_username (_new_username )
143170
144171 if _new_email :
145- current_user .update_email (_new_email )
172+ self .update_email (_new_email )
146173
147- current_user .save ()
174+ self .save ()
148175
149176 return {"success" : True }, 200
150177
@@ -156,18 +183,17 @@ class LogoutUser(Resource):
156183 """
157184
158185 @rest_api .expect (logout_model , validate = True )
159- @jwt_required ()
160- def post (self ):
186+ @token_required
187+ def post (self , current_user ):
161188
162- user_email = get_jwt_identity ()
163- current_user = Users .get_by_email (user_email )
164-
165- if not current_user :
166- return {"success" : False ,
167- "msg" : "Sorry. Wrong auth token" }, 400
189+ req_data = request .get_json ()
190+ _jwt_token = req_data .get ("token" )
168191
169- jwt_block = JWTTokenBlocklist (jti = get_jwt ()[ "jti" ] , created_at = datetime .now (timezone .utc ))
192+ jwt_block = JWTTokenBlocklist (jwt_token = _jwt_token , created_at = datetime .now (timezone .utc ))
170193 jwt_block .save ()
171194
195+ self .set_jwt_auth_active (False )
196+ self .save ()
197+
172198 return {"success" : True ,
173199 "msg" : "JWT Token revoked successfully" }, 200
0 commit comments