We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Tickets endpoint results in too many redirects in production.
```python
            try:
                response = make_response(send_file(file_path))
                response.headers['Content-Disposition'] = 'attachment; filename=ticket-%s.pdf' % order_identifier
                return response
            except FileNotFoundError:
                create_pdf_tickets_for_holder(order)
                return redirect(url_for('ticket_blueprint.ticket_attendee_authorized', order_identifier=order_identifier))
```

The redirect call seems to be the problem, removing it and manually sending the response seems to fix it.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `app/api/auth.py`
Content:
```
1 import os
2 import base64
3 import random
4 import string
5 
6 import requests
7 from flask import request, jsonify, make_response, Blueprint, send_file, url_for, redirect
8 from flask_jwt import current_identity as current_user, jwt_required
9 from sqlalchemy.orm.exc import NoResultFound
10 from app.api.helpers.order import create_pdf_tickets_for_holder
11 from app.api.helpers.storage import generate_hash
12 
13 from app import get_settings
14 from app.api.helpers.db import save_to_db, get_count
15 from app.api.helpers.errors import ForbiddenError, UnprocessableEntityError, NotFoundError, BadRequestError
16 from app.api.helpers.files import make_frontend_url
17 from app.api.helpers.mail import send_email_with_action, \
18     send_email_confirmation
19 from app.api.helpers.notification import send_notification_with_action
20 from app.api.helpers.third_party_auth import GoogleOAuth, FbOAuth, TwitterOAuth, InstagramOAuth
21 from app.api.helpers.utilities import get_serializer, str_generator
22 from app.models import db
23 from app.models.order import Order
24 from app.models.mail import PASSWORD_RESET, PASSWORD_CHANGE, \
25     USER_REGISTER_WITH_PASSWORD, PASSWORD_RESET_AND_VERIFY
26 from app.models.notification import PASSWORD_CHANGE as PASSWORD_CHANGE_NOTIF
27 from app.models.user import User
28 from app.api.helpers.storage import UPLOAD_PATHS
29 
30 
31 ticket_blueprint = Blueprint('ticket_blueprint', __name__, url_prefix='/v1')
32 auth_routes = Blueprint('auth', __name__, url_prefix='/v1/auth')
33 
34 
35 @auth_routes.route('/oauth/<provider>', methods=['GET'])
36 def redirect_uri(provider):
37     if provider == 'facebook':
38         provider_class = FbOAuth()
39     elif provider == 'google':
40         provider_class = GoogleOAuth()
41     elif provider == 'twitter':
42         provider_class = TwitterOAuth()
43     elif provider == 'instagram':
44         provider_class = InstagramOAuth()
45     else:
46         return make_response(jsonify(
47             message="No support for {}".format(provider)), 404)
48 
49     client_id = provider_class.get_client_id()
50     if not client_id:
51         return make_response(jsonify(
52             message="{} client id is not configured on the server".format(provider)), 404)
53 
54     url = provider_class.get_auth_uri() + '?client_id=' + \
55           client_id + '&redirect_uri=' + \
56           provider_class.get_redirect_uri()
57     return make_response(jsonify(url=url), 200)
58 
59 
60 @auth_routes.route('/oauth/token/<provider>', methods=['GET'])
61 def get_token(provider):
62     if provider == 'facebook':
63         provider_class = FbOAuth()
64         payload = {
65             'grant_type': 'client_credentials',
66             'client_id': provider_class.get_client_id(),
67             'client_secret': provider_class.get_client_secret()
68         }
69     elif provider == 'google':
70         provider_class = GoogleOAuth()
71         payload = {
72             'client_id': provider_class.get_client_id(),
73             'client_secret': provider_class.get_client_secret()
74         }
75     elif provider == 'twitter':
76         provider_class = TwitterOAuth()
77         payload = {
78             'client_id': provider_class.get_client_id(),
79             'client_secret': provider_class.get_client_secret()
80         }
81     elif provider == 'instagram':
82         provider_class = InstagramOAuth()
83         payload = {
84             'client_id': provider_class.get_client_id(),
85             'client_secret': provider_class.get_client_secret()
86         }
87     else:
88         return make_response(jsonify(
89             message="No support for {}".format(provider)), 200)
90     response = requests.post(provider_class.get_token_uri(), params=payload)
91     return make_response(jsonify(token=response.json()), 200)
92 
93 
94 @auth_routes.route('/oauth/login/<provider>', methods=['POST'])
95 def login_user(provider):
96     if provider == 'facebook':
97         provider_class = FbOAuth()
98         payload = {
99             'client_id': provider_class.get_client_id(),
100             'redirect_uri': provider_class.get_redirect_uri(),
101             'client_secret': provider_class.get_client_secret(),
102             'code': request.args.get('code')
103         }
104         if not payload['client_id'] or not payload['client_secret']:
105             raise NotImplementedError({'source': ''}, 'Facebook Login Not Configured')
106         access_token = requests.get('https://graph.facebook.com/v3.0/oauth/access_token', params=payload).json()
107         payload_details = {
108             'input_token': access_token['access_token'],
109             'access_token': provider_class.get_client_id() + '|' + provider_class.get_client_secret()
110         }
111         details = requests.get('https://graph.facebook.com/debug_token', params=payload_details).json()
112         user_details = requests.get('https://graph.facebook.com/v3.0/' + details['data']['user_id'],
113                                     params={'access_token': access_token['access_token'],
114                                             'fields': 'first_name, last_name, email'}).json()
115 
116         if get_count(db.session.query(User).filter_by(email=user_details['email'])) > 0:
117             user = db.session.query(User).filter_by(email=user_details['email']).one()
118             if not user.facebook_id:
119                 user.facebook_id = user_details['id']
120                 user.facebook_login_hash = random.getrandbits(128)
121                 save_to_db(user)
122             return make_response(
123                 jsonify(user_id=user.id, email=user.email, oauth_hash=user.facebook_login_hash), 200)
124 
125         user = User()
126         user.first_name = user_details['first_name']
127         user.last_name = user_details['last_name']
128         user.facebook_id = user_details['id']
129         user.facebook_login_hash = random.getrandbits(128)
130         user.password = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(8))
131         if user_details['email']:
132             user.email = user_details['email']
133 
134         save_to_db(user)
135         return make_response(jsonify(user_id=user.id, email=user.email, oauth_hash=user.facebook_login_hash),
136                              200)
137 
138     elif provider == 'google':
139         provider_class = GoogleOAuth()
140         payload = {
141             'client_id': provider_class.get_client_id(),
142             'client_secret': provider_class.get_client_secret()
143         }
144     elif provider == 'twitter':
145         provider_class = TwitterOAuth()
146         payload = {
147             'client_id': provider_class.get_client_id(),
148             'client_secret': provider_class.get_client_secret()
149         }
150     elif provider == 'instagram':
151         provider_class = InstagramOAuth()
152         payload = {
153             'client_id': provider_class.get_client_id(),
154             'client_secret': provider_class.get_client_secret()
155         }
156     else:
157         return make_response(jsonify(
158             message="No support for {}".format(provider)), 200)
159     response = requests.post(provider_class.get_token_uri(), params=payload)
160     return make_response(jsonify(token=response.json()), 200)
161 
162 
163 @auth_routes.route('/verify-email', methods=['POST'])
164 def verify_email():
165     token = base64.b64decode(request.json['data']['token'])
166     s = get_serializer()
167 
168     try:
169         data = s.loads(token)
170     except Exception:
171         return BadRequestError({'source': ''}, 'Invalid Token').respond()
172 
173     try:
174         user = User.query.filter_by(email=data[0]).one()
175     except Exception:
176         return BadRequestError({'source': ''}, 'Invalid Token').respond()
177     else:
178         user.is_verified = True
179         save_to_db(user)
180         return make_response(jsonify(message="Email Verified"), 200)
181 
182 
183 @auth_routes.route('/resend-verification-email', methods=['POST'])
184 def resend_verification_email():
185     try:
186         email = request.json['data']['email']
187     except TypeError:
188         return BadRequestError({'source': ''}, 'Bad Request Error').respond()
189 
190     try:
191         user = User.query.filter_by(email=email).one()
192     except NoResultFound:
193         return UnprocessableEntityError(
194             {'source': ''}, 'User with email: ' + email + ' not found.').respond()
195     else:
196         serializer = get_serializer()
197         hash_ = str(base64.b64encode(str(serializer.dumps(
198             [user.email, str_generator()])).encode()), 'utf-8')
199         link = make_frontend_url(
200             '/verify'.format(id=user.id), {'token': hash_})
201         send_email_confirmation(user.email, link)
202 
203         return make_response(jsonify(message="Verification email resent"), 200)
204 
205 
206 @auth_routes.route('/reset-password', methods=['POST'])
207 def reset_password_post():
208     try:
209         email = request.json['data']['email']
210     except TypeError:
211         return BadRequestError({'source': ''}, 'Bad Request Error').respond()
212 
213     try:
214         user = User.query.filter_by(email=email).one()
215     except NoResultFound:
216         return NotFoundError({'source': ''}, 'User not found').respond()
217     else:
218         link = make_frontend_url('/reset-password', {'token': user.reset_password})
219         if user.was_registered_with_order:
220             send_email_with_action(user, PASSWORD_RESET_AND_VERIFY, app_name=get_settings()['app_name'], link=link)
221         else:
222             send_email_with_action(user, PASSWORD_RESET, app_name=get_settings()['app_name'], link=link)
223 
224     return make_response(jsonify(message="Email Sent"), 200)
225 
226 
227 @auth_routes.route('/reset-password', methods=['PATCH'])
228 def reset_password_patch():
229     token = request.json['data']['token']
230     password = request.json['data']['password']
231 
232     try:
233         user = User.query.filter_by(reset_password=token).one()
234     except NoResultFound:
235         return NotFoundError({'source': ''}, 'User Not Found').respond()
236     else:
237         user.password = password
238         if user.was_registered_with_order:
239             user.is_verified = True
240         save_to_db(user)
241 
242     return jsonify({
243         "id": user.id,
244         "email": user.email,
245         "name": user.fullname if user.fullname else None
246     })
247 
248 
249 @auth_routes.route('/change-password', methods=['POST'])
250 @jwt_required()
251 def change_password():
252     old_password = request.json['data']['old-password']
253     new_password = request.json['data']['new-password']
254 
255     try:
256         user = User.query.filter_by(id=current_user.id).one()
257     except NoResultFound:
258         return NotFoundError({'source': ''}, 'User Not Found').respond()
259     else:
260         if user.is_correct_password(old_password):
261             if user.is_correct_password(new_password):
262                 return BadRequestError({'source': ''},
263                                        'Old and New passwords must be different').respond()
264             if len(new_password) < 8:
265                 return BadRequestError({'source': ''},
266                                        'Password should have minimum 8 characters').respond()
267             user.password = new_password
268             save_to_db(user)
269             send_email_with_action(user, PASSWORD_CHANGE,
270                                    app_name=get_settings()['app_name'])
271             send_notification_with_action(user, PASSWORD_CHANGE_NOTIF,
272                                           app_name=get_settings()['app_name'])
273         else:
274             return BadRequestError({'source': ''}, 'Wrong Password. Please enter correct current password.').respond()
275 
276     return jsonify({
277         "id": user.id,
278         "email": user.email,
279         "name": user.fullname if user.fullname else None,
280         "password-changed": True
281     })
282 
283 
284 @ticket_blueprint.route('/tickets/<string:order_identifier>')
285 @jwt_required()
286 def ticket_attendee_authorized(order_identifier):
287     if current_user:
288         try:
289             order = Order.query.filter_by(identifier=order_identifier).first()
290             user_id = order.user.id
291         except NoResultFound:
292             return NotFoundError({'source': ''}, 'This ticket is not associated with any order').respond()
293         if current_user.id == user_id:
294             key = UPLOAD_PATHS['pdf']['ticket_attendee'].format(identifier=order_identifier)
295             file_path = '../generated/tickets/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'
296             try:
297                 response = make_response(send_file(file_path))
298                 response.headers['Content-Disposition'] = 'attachment; filename=ticket-%s.zip' % order_identifier
299                 return response
300             except FileNotFoundError:
301                 create_pdf_tickets_for_holder(order)
302                 return redirect(url_for('ticket_blueprint.ticket_attendee_authorized', order_identifier=order_identifier))
303         else:
304             return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()
305     else:
306         return ForbiddenError({'source': ''}, 'Authentication Required to access ticket').respond()
307 
308 
309 @ticket_blueprint.route('/orders/invoices/<string:order_identifier>')
310 @jwt_required()
311 def order_invoices(order_identifier):
312     if current_user:
313         try:
314             order = Order.query.filter_by(identifier=order_identifier).first()
315             user_id = order.user.id
316         except NoResultFound:
317             return NotFoundError({'source': ''}, 'Order Invoice not found').respond()
318         if current_user.id == user_id:
319             key = UPLOAD_PATHS['pdf']['order'].format(identifier=order_identifier)
320             file_path = '../generated/invoices/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'
321             response = make_response(send_file(file_path))
322             response.headers['Content-Disposition'] = 'attachment; filename=invoice-%s.zip' % order_identifier
323             return response
324         else:
325             return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()
326     else:
327         return ForbiddenError({'source': ''}, 'Authentication Required to access Invoice').respond()
328
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/app/api/auth.py b/app/api/auth.py
--- a/app/api/auth.py
+++ b/app/api/auth.py
@@ -281,6 +281,11 @@
     })
 
 
+def return_tickets(file_path, order_identifier):
+    response = make_response(send_file(file_path))
+    response.headers['Content-Disposition'] = 'attachment; filename=ticket-%s.pdf' % order_identifier
+    return response
+
 @ticket_blueprint.route('/tickets/<string:order_identifier>')
 @jwt_required()
 def ticket_attendee_authorized(order_identifier):
@@ -294,12 +299,10 @@
             key = UPLOAD_PATHS['pdf']['ticket_attendee'].format(identifier=order_identifier)
             file_path = '../generated/tickets/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'
             try:
-                response = make_response(send_file(file_path))
-                response.headers['Content-Disposition'] = 'attachment; filename=ticket-%s.zip' % order_identifier
-                return response
+                return return_tickets(file_path, order_identifier)
             except FileNotFoundError:
                 create_pdf_tickets_for_holder(order)
-                return redirect(url_for('ticket_blueprint.ticket_attendee_authorized', order_identifier=order_identifier))
+                return return_tickets(file_path, order_identifier)
         else:
             return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()
     else:

{"golden_diff": "diff --git a/app/api/auth.py b/app/api/auth.py\n--- a/app/api/auth.py\n+++ b/app/api/auth.py\n@@ -281,6 +281,11 @@\n     })\n \n \n+def return_tickets(file_path, order_identifier):\n+    response = make_response(send_file(file_path))\n+    response.headers['Content-Disposition'] = 'attachment; filename=ticket-%s.pdf' % order_identifier\n+    return response\n+\n @ticket_blueprint.route('/tickets/<string:order_identifier>')\n @jwt_required()\n def ticket_attendee_authorized(order_identifier):\n@@ -294,12 +299,10 @@\n             key = UPLOAD_PATHS['pdf']['ticket_attendee'].format(identifier=order_identifier)\n             file_path = '../generated/tickets/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'\n             try:\n-                response = make_response(send_file(file_path))\n-                response.headers['Content-Disposition'] = 'attachment; filename=ticket-%s.zip' % order_identifier\n-                return response\n+                return return_tickets(file_path, order_identifier)\n             except FileNotFoundError:\n                 create_pdf_tickets_for_holder(order)\n-                return redirect(url_for('ticket_blueprint.ticket_attendee_authorized', order_identifier=order_identifier))\n+                return return_tickets(file_path, order_identifier)\n         else:\n             return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()\n     else:\n", "issue": "Tickets endpoint results in too many redirects in production.\n```python\r\n            try:\r\n                response = make_response(send_file(file_path))\r\n                response.headers['Content-Disposition'] = 'attachment; filename=ticket-%s.pdf' % order_identifier\r\n                return response\r\n            except FileNotFoundError:\r\n                create_pdf_tickets_for_holder(order)\r\n                return redirect(url_for('ticket_blueprint.ticket_attendee_authorized', order_identifier=order_identifier))\r\n```\r\n\r\nThe redirect call seems to be the problem, removing it and manually sending the response seems to fix it.\r\n\n", "before_files": [{"content": "import os\nimport base64\nimport random\nimport string\n\nimport requests\nfrom flask import request, jsonify, make_response, Blueprint, send_file, url_for, redirect\nfrom flask_jwt import current_identity as current_user, jwt_required\nfrom sqlalchemy.orm.exc import NoResultFound\nfrom app.api.helpers.order import create_pdf_tickets_for_holder\nfrom app.api.helpers.storage import generate_hash\n\nfrom app import get_settings\nfrom app.api.helpers.db import save_to_db, get_count\nfrom app.api.helpers.errors import ForbiddenError, UnprocessableEntityError, NotFoundError, BadRequestError\nfrom app.api.helpers.files import make_frontend_url\nfrom app.api.helpers.mail import send_email_with_action, \\\n    send_email_confirmation\nfrom app.api.helpers.notification import send_notification_with_action\nfrom app.api.helpers.third_party_auth import GoogleOAuth, FbOAuth, TwitterOAuth, InstagramOAuth\nfrom app.api.helpers.utilities import get_serializer, str_generator\nfrom app.models import db\nfrom app.models.order import Order\nfrom app.models.mail import PASSWORD_RESET, PASSWORD_CHANGE, \\\n    USER_REGISTER_WITH_PASSWORD, PASSWORD_RESET_AND_VERIFY\nfrom app.models.notification import PASSWORD_CHANGE as PASSWORD_CHANGE_NOTIF\nfrom app.models.user import User\nfrom app.api.helpers.storage import UPLOAD_PATHS\n\n\nticket_blueprint = Blueprint('ticket_blueprint', __name__, url_prefix='/v1')\nauth_routes = Blueprint('auth', __name__, url_prefix='/v1/auth')\n\n\n@auth_routes.route('/oauth/<provider>', methods=['GET'])\ndef redirect_uri(provider):\n    if provider == 'facebook':\n        provider_class = FbOAuth()\n    elif provider == 'google':\n        provider_class = GoogleOAuth()\n    elif provider == 'twitter':\n        provider_class = TwitterOAuth()\n    elif provider == 'instagram':\n        provider_class = InstagramOAuth()\n    else:\n        return make_response(jsonify(\n            message=\"No support for {}\".format(provider)), 404)\n\n    client_id = provider_class.get_client_id()\n    if not client_id:\n        return make_response(jsonify(\n            message=\"{} client id is not configured on the server\".format(provider)), 404)\n\n    url = provider_class.get_auth_uri() + '?client_id=' + \\\n          client_id + '&redirect_uri=' + \\\n          provider_class.get_redirect_uri()\n    return make_response(jsonify(url=url), 200)\n\n\n@auth_routes.route('/oauth/token/<provider>', methods=['GET'])\ndef get_token(provider):\n    if provider == 'facebook':\n        provider_class = FbOAuth()\n        payload = {\n            'grant_type': 'client_credentials',\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    elif provider == 'google':\n        provider_class = GoogleOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    elif provider == 'twitter':\n        provider_class = TwitterOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    elif provider == 'instagram':\n        provider_class = InstagramOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    else:\n        return make_response(jsonify(\n            message=\"No support for {}\".format(provider)), 200)\n    response = requests.post(provider_class.get_token_uri(), params=payload)\n    return make_response(jsonify(token=response.json()), 200)\n\n\n@auth_routes.route('/oauth/login/<provider>', methods=['POST'])\ndef login_user(provider):\n    if provider == 'facebook':\n        provider_class = FbOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'redirect_uri': provider_class.get_redirect_uri(),\n            'client_secret': provider_class.get_client_secret(),\n            'code': request.args.get('code')\n        }\n        if not payload['client_id'] or not payload['client_secret']:\n            raise NotImplementedError({'source': ''}, 'Facebook Login Not Configured')\n        access_token = requests.get('https://graph.facebook.com/v3.0/oauth/access_token', params=payload).json()\n        payload_details = {\n            'input_token': access_token['access_token'],\n            'access_token': provider_class.get_client_id() + '|' + provider_class.get_client_secret()\n        }\n        details = requests.get('https://graph.facebook.com/debug_token', params=payload_details).json()\n        user_details = requests.get('https://graph.facebook.com/v3.0/' + details['data']['user_id'],\n                                    params={'access_token': access_token['access_token'],\n                                            'fields': 'first_name, last_name, email'}).json()\n\n        if get_count(db.session.query(User).filter_by(email=user_details['email'])) > 0:\n            user = db.session.query(User).filter_by(email=user_details['email']).one()\n            if not user.facebook_id:\n                user.facebook_id = user_details['id']\n                user.facebook_login_hash = random.getrandbits(128)\n                save_to_db(user)\n            return make_response(\n                jsonify(user_id=user.id, email=user.email, oauth_hash=user.facebook_login_hash), 200)\n\n        user = User()\n        user.first_name = user_details['first_name']\n        user.last_name = user_details['last_name']\n        user.facebook_id = user_details['id']\n        user.facebook_login_hash = random.getrandbits(128)\n        user.password = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(8))\n        if user_details['email']:\n            user.email = user_details['email']\n\n        save_to_db(user)\n        return make_response(jsonify(user_id=user.id, email=user.email, oauth_hash=user.facebook_login_hash),\n                             200)\n\n    elif provider == 'google':\n        provider_class = GoogleOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    elif provider == 'twitter':\n        provider_class = TwitterOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    elif provider == 'instagram':\n        provider_class = InstagramOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    else:\n        return make_response(jsonify(\n            message=\"No support for {}\".format(provider)), 200)\n    response = requests.post(provider_class.get_token_uri(), params=payload)\n    return make_response(jsonify(token=response.json()), 200)\n\n\n@auth_routes.route('/verify-email', methods=['POST'])\ndef verify_email():\n    token = base64.b64decode(request.json['data']['token'])\n    s = get_serializer()\n\n    try:\n        data = s.loads(token)\n    except Exception:\n        return BadRequestError({'source': ''}, 'Invalid Token').respond()\n\n    try:\n        user = User.query.filter_by(email=data[0]).one()\n    except Exception:\n        return BadRequestError({'source': ''}, 'Invalid Token').respond()\n    else:\n        user.is_verified = True\n        save_to_db(user)\n        return make_response(jsonify(message=\"Email Verified\"), 200)\n\n\n@auth_routes.route('/resend-verification-email', methods=['POST'])\ndef resend_verification_email():\n    try:\n        email = request.json['data']['email']\n    except TypeError:\n        return BadRequestError({'source': ''}, 'Bad Request Error').respond()\n\n    try:\n        user = User.query.filter_by(email=email).one()\n    except NoResultFound:\n        return UnprocessableEntityError(\n            {'source': ''}, 'User with email: ' + email + ' not found.').respond()\n    else:\n        serializer = get_serializer()\n        hash_ = str(base64.b64encode(str(serializer.dumps(\n            [user.email, str_generator()])).encode()), 'utf-8')\n        link = make_frontend_url(\n            '/verify'.format(id=user.id), {'token': hash_})\n        send_email_confirmation(user.email, link)\n\n        return make_response(jsonify(message=\"Verification email resent\"), 200)\n\n\n@auth_routes.route('/reset-password', methods=['POST'])\ndef reset_password_post():\n    try:\n        email = request.json['data']['email']\n    except TypeError:\n        return BadRequestError({'source': ''}, 'Bad Request Error').respond()\n\n    try:\n        user = User.query.filter_by(email=email).one()\n    except NoResultFound:\n        return NotFoundError({'source': ''}, 'User not found').respond()\n    else:\n        link = make_frontend_url('/reset-password', {'token': user.reset_password})\n        if user.was_registered_with_order:\n            send_email_with_action(user, PASSWORD_RESET_AND_VERIFY, app_name=get_settings()['app_name'], link=link)\n        else:\n            send_email_with_action(user, PASSWORD_RESET, app_name=get_settings()['app_name'], link=link)\n\n    return make_response(jsonify(message=\"Email Sent\"), 200)\n\n\n@auth_routes.route('/reset-password', methods=['PATCH'])\ndef reset_password_patch():\n    token = request.json['data']['token']\n    password = request.json['data']['password']\n\n    try:\n        user = User.query.filter_by(reset_password=token).one()\n    except NoResultFound:\n        return NotFoundError({'source': ''}, 'User Not Found').respond()\n    else:\n        user.password = password\n        if user.was_registered_with_order:\n            user.is_verified = True\n        save_to_db(user)\n\n    return jsonify({\n        \"id\": user.id,\n        \"email\": user.email,\n        \"name\": user.fullname if user.fullname else None\n    })\n\n\n@auth_routes.route('/change-password', methods=['POST'])\n@jwt_required()\ndef change_password():\n    old_password = request.json['data']['old-password']\n    new_password = request.json['data']['new-password']\n\n    try:\n        user = User.query.filter_by(id=current_user.id).one()\n    except NoResultFound:\n        return NotFoundError({'source': ''}, 'User Not Found').respond()\n    else:\n        if user.is_correct_password(old_password):\n            if user.is_correct_password(new_password):\n                return BadRequestError({'source': ''},\n                                       'Old and New passwords must be different').respond()\n            if len(new_password) < 8:\n                return BadRequestError({'source': ''},\n                                       'Password should have minimum 8 characters').respond()\n            user.password = new_password\n            save_to_db(user)\n            send_email_with_action(user, PASSWORD_CHANGE,\n                                   app_name=get_settings()['app_name'])\n            send_notification_with_action(user, PASSWORD_CHANGE_NOTIF,\n                                          app_name=get_settings()['app_name'])\n        else:\n            return BadRequestError({'source': ''}, 'Wrong Password. Please enter correct current password.').respond()\n\n    return jsonify({\n        \"id\": user.id,\n        \"email\": user.email,\n        \"name\": user.fullname if user.fullname else None,\n        \"password-changed\": True\n    })\n\n\n@ticket_blueprint.route('/tickets/<string:order_identifier>')\n@jwt_required()\ndef ticket_attendee_authorized(order_identifier):\n    if current_user:\n        try:\n            order = Order.query.filter_by(identifier=order_identifier).first()\n            user_id = order.user.id\n        except NoResultFound:\n            return NotFoundError({'source': ''}, 'This ticket is not associated with any order').respond()\n        if current_user.id == user_id:\n            key = UPLOAD_PATHS['pdf']['ticket_attendee'].format(identifier=order_identifier)\n            file_path = '../generated/tickets/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'\n            try:\n                response = make_response(send_file(file_path))\n                response.headers['Content-Disposition'] = 'attachment; filename=ticket-%s.zip' % order_identifier\n                return response\n            except FileNotFoundError:\n                create_pdf_tickets_for_holder(order)\n                return redirect(url_for('ticket_blueprint.ticket_attendee_authorized', order_identifier=order_identifier))\n        else:\n            return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()\n    else:\n        return ForbiddenError({'source': ''}, 'Authentication Required to access ticket').respond()\n\n\n@ticket_blueprint.route('/orders/invoices/<string:order_identifier>')\n@jwt_required()\ndef order_invoices(order_identifier):\n    if current_user:\n        try:\n            order = Order.query.filter_by(identifier=order_identifier).first()\n            user_id = order.user.id\n        except NoResultFound:\n            return NotFoundError({'source': ''}, 'Order Invoice not found').respond()\n        if current_user.id == user_id:\n            key = UPLOAD_PATHS['pdf']['order'].format(identifier=order_identifier)\n            file_path = '../generated/invoices/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'\n            response = make_response(send_file(file_path))\n            response.headers['Content-Disposition'] = 'attachment; filename=invoice-%s.zip' % order_identifier\n            return response\n        else:\n            return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()\n    else:\n        return ForbiddenError({'source': ''}, 'Authentication Required to access Invoice').respond()\n", "path": "app/api/auth.py"}], "after_files": [{"content": "import os\nimport base64\nimport random\nimport string\n\nimport requests\nfrom flask import request, jsonify, make_response, Blueprint, send_file, url_for, redirect\nfrom flask_jwt import current_identity as current_user, jwt_required\nfrom sqlalchemy.orm.exc import NoResultFound\nfrom app.api.helpers.order import create_pdf_tickets_for_holder\nfrom app.api.helpers.storage import generate_hash\n\nfrom app import get_settings\nfrom app.api.helpers.db import save_to_db, get_count\nfrom app.api.helpers.errors import ForbiddenError, UnprocessableEntityError, NotFoundError, BadRequestError\nfrom app.api.helpers.files import make_frontend_url\nfrom app.api.helpers.mail import send_email_with_action, \\\n    send_email_confirmation\nfrom app.api.helpers.notification import send_notification_with_action\nfrom app.api.helpers.third_party_auth import GoogleOAuth, FbOAuth, TwitterOAuth, InstagramOAuth\nfrom app.api.helpers.utilities import get_serializer, str_generator\nfrom app.models import db\nfrom app.models.order import Order\nfrom app.models.mail import PASSWORD_RESET, PASSWORD_CHANGE, \\\n    USER_REGISTER_WITH_PASSWORD, PASSWORD_RESET_AND_VERIFY\nfrom app.models.notification import PASSWORD_CHANGE as PASSWORD_CHANGE_NOTIF\nfrom app.models.user import User\nfrom app.api.helpers.storage import UPLOAD_PATHS\n\n\nticket_blueprint = Blueprint('ticket_blueprint', __name__, url_prefix='/v1')\nauth_routes = Blueprint('auth', __name__, url_prefix='/v1/auth')\n\n\n@auth_routes.route('/oauth/<provider>', methods=['GET'])\ndef redirect_uri(provider):\n    if provider == 'facebook':\n        provider_class = FbOAuth()\n    elif provider == 'google':\n        provider_class = GoogleOAuth()\n    elif provider == 'twitter':\n        provider_class = TwitterOAuth()\n    elif provider == 'instagram':\n        provider_class = InstagramOAuth()\n    else:\n        return make_response(jsonify(\n            message=\"No support for {}\".format(provider)), 404)\n\n    client_id = provider_class.get_client_id()\n    if not client_id:\n        return make_response(jsonify(\n            message=\"{} client id is not configured on the server\".format(provider)), 404)\n\n    url = provider_class.get_auth_uri() + '?client_id=' + \\\n          client_id + '&redirect_uri=' + \\\n          provider_class.get_redirect_uri()\n    return make_response(jsonify(url=url), 200)\n\n\n@auth_routes.route('/oauth/token/<provider>', methods=['GET'])\ndef get_token(provider):\n    if provider == 'facebook':\n        provider_class = FbOAuth()\n        payload = {\n            'grant_type': 'client_credentials',\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    elif provider == 'google':\n        provider_class = GoogleOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    elif provider == 'twitter':\n        provider_class = TwitterOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    elif provider == 'instagram':\n        provider_class = InstagramOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    else:\n        return make_response(jsonify(\n            message=\"No support for {}\".format(provider)), 200)\n    response = requests.post(provider_class.get_token_uri(), params=payload)\n    return make_response(jsonify(token=response.json()), 200)\n\n\n@auth_routes.route('/oauth/login/<provider>', methods=['POST'])\ndef login_user(provider):\n    if provider == 'facebook':\n        provider_class = FbOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'redirect_uri': provider_class.get_redirect_uri(),\n            'client_secret': provider_class.get_client_secret(),\n            'code': request.args.get('code')\n        }\n        if not payload['client_id'] or not payload['client_secret']:\n            raise NotImplementedError({'source': ''}, 'Facebook Login Not Configured')\n        access_token = requests.get('https://graph.facebook.com/v3.0/oauth/access_token', params=payload).json()\n        payload_details = {\n            'input_token': access_token['access_token'],\n            'access_token': provider_class.get_client_id() + '|' + provider_class.get_client_secret()\n        }\n        details = requests.get('https://graph.facebook.com/debug_token', params=payload_details).json()\n        user_details = requests.get('https://graph.facebook.com/v3.0/' + details['data']['user_id'],\n                                    params={'access_token': access_token['access_token'],\n                                            'fields': 'first_name, last_name, email'}).json()\n\n        if get_count(db.session.query(User).filter_by(email=user_details['email'])) > 0:\n            user = db.session.query(User).filter_by(email=user_details['email']).one()\n            if not user.facebook_id:\n                user.facebook_id = user_details['id']\n                user.facebook_login_hash = random.getrandbits(128)\n                save_to_db(user)\n            return make_response(\n                jsonify(user_id=user.id, email=user.email, oauth_hash=user.facebook_login_hash), 200)\n\n        user = User()\n        user.first_name = user_details['first_name']\n        user.last_name = user_details['last_name']\n        user.facebook_id = user_details['id']\n        user.facebook_login_hash = random.getrandbits(128)\n        user.password = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(8))\n        if user_details['email']:\n            user.email = user_details['email']\n\n        save_to_db(user)\n        return make_response(jsonify(user_id=user.id, email=user.email, oauth_hash=user.facebook_login_hash),\n                             200)\n\n    elif provider == 'google':\n        provider_class = GoogleOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    elif provider == 'twitter':\n        provider_class = TwitterOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    elif provider == 'instagram':\n        provider_class = InstagramOAuth()\n        payload = {\n            'client_id': provider_class.get_client_id(),\n            'client_secret': provider_class.get_client_secret()\n        }\n    else:\n        return make_response(jsonify(\n            message=\"No support for {}\".format(provider)), 200)\n    response = requests.post(provider_class.get_token_uri(), params=payload)\n    return make_response(jsonify(token=response.json()), 200)\n\n\n@auth_routes.route('/verify-email', methods=['POST'])\ndef verify_email():\n    token = base64.b64decode(request.json['data']['token'])\n    s = get_serializer()\n\n    try:\n        data = s.loads(token)\n    except Exception:\n        return BadRequestError({'source': ''}, 'Invalid Token').respond()\n\n    try:\n        user = User.query.filter_by(email=data[0]).one()\n    except Exception:\n        return BadRequestError({'source': ''}, 'Invalid Token').respond()\n    else:\n        user.is_verified = True\n        save_to_db(user)\n        return make_response(jsonify(message=\"Email Verified\"), 200)\n\n\n@auth_routes.route('/resend-verification-email', methods=['POST'])\ndef resend_verification_email():\n    try:\n        email = request.json['data']['email']\n    except TypeError:\n        return BadRequestError({'source': ''}, 'Bad Request Error').respond()\n\n    try:\n        user = User.query.filter_by(email=email).one()\n    except NoResultFound:\n        return UnprocessableEntityError(\n            {'source': ''}, 'User with email: ' + email + ' not found.').respond()\n    else:\n        serializer = get_serializer()\n        hash_ = str(base64.b64encode(str(serializer.dumps(\n            [user.email, str_generator()])).encode()), 'utf-8')\n        link = make_frontend_url(\n            '/verify'.format(id=user.id), {'token': hash_})\n        send_email_confirmation(user.email, link)\n\n        return make_response(jsonify(message=\"Verification email resent\"), 200)\n\n\n@auth_routes.route('/reset-password', methods=['POST'])\ndef reset_password_post():\n    try:\n        email = request.json['data']['email']\n    except TypeError:\n        return BadRequestError({'source': ''}, 'Bad Request Error').respond()\n\n    try:\n        user = User.query.filter_by(email=email).one()\n    except NoResultFound:\n        return NotFoundError({'source': ''}, 'User not found').respond()\n    else:\n        link = make_frontend_url('/reset-password', {'token': user.reset_password})\n        if user.was_registered_with_order:\n            send_email_with_action(user, PASSWORD_RESET_AND_VERIFY, app_name=get_settings()['app_name'], link=link)\n        else:\n            send_email_with_action(user, PASSWORD_RESET, app_name=get_settings()['app_name'], link=link)\n\n    return make_response(jsonify(message=\"Email Sent\"), 200)\n\n\n@auth_routes.route('/reset-password', methods=['PATCH'])\ndef reset_password_patch():\n    token = request.json['data']['token']\n    password = request.json['data']['password']\n\n    try:\n        user = User.query.filter_by(reset_password=token).one()\n    except NoResultFound:\n        return NotFoundError({'source': ''}, 'User Not Found').respond()\n    else:\n        user.password = password\n        if user.was_registered_with_order:\n            user.is_verified = True\n        save_to_db(user)\n\n    return jsonify({\n        \"id\": user.id,\n        \"email\": user.email,\n        \"name\": user.fullname if user.fullname else None\n    })\n\n\n@auth_routes.route('/change-password', methods=['POST'])\n@jwt_required()\ndef change_password():\n    old_password = request.json['data']['old-password']\n    new_password = request.json['data']['new-password']\n\n    try:\n        user = User.query.filter_by(id=current_user.id).one()\n    except NoResultFound:\n        return NotFoundError({'source': ''}, 'User Not Found').respond()\n    else:\n        if user.is_correct_password(old_password):\n            if user.is_correct_password(new_password):\n                return BadRequestError({'source': ''},\n                                       'Old and New passwords must be different').respond()\n            if len(new_password) < 8:\n                return BadRequestError({'source': ''},\n                                       'Password should have minimum 8 characters').respond()\n            user.password = new_password\n            save_to_db(user)\n            send_email_with_action(user, PASSWORD_CHANGE,\n                                   app_name=get_settings()['app_name'])\n            send_notification_with_action(user, PASSWORD_CHANGE_NOTIF,\n                                          app_name=get_settings()['app_name'])\n        else:\n            return BadRequestError({'source': ''}, 'Wrong Password. Please enter correct current password.').respond()\n\n    return jsonify({\n        \"id\": user.id,\n        \"email\": user.email,\n        \"name\": user.fullname if user.fullname else None,\n        \"password-changed\": True\n    })\n\n\ndef return_tickets(file_path, order_identifier):\n    response = make_response(send_file(file_path))\n    response.headers['Content-Disposition'] = 'attachment; filename=ticket-%s.pdf' % order_identifier\n    return response\n\n@ticket_blueprint.route('/tickets/<string:order_identifier>')\n@jwt_required()\ndef ticket_attendee_authorized(order_identifier):\n    if current_user:\n        try:\n            order = Order.query.filter_by(identifier=order_identifier).first()\n            user_id = order.user.id\n        except NoResultFound:\n            return NotFoundError({'source': ''}, 'This ticket is not associated with any order').respond()\n        if current_user.id == user_id:\n            key = UPLOAD_PATHS['pdf']['ticket_attendee'].format(identifier=order_identifier)\n            file_path = '../generated/tickets/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'\n            try:\n                return return_tickets(file_path, order_identifier)\n            except FileNotFoundError:\n                create_pdf_tickets_for_holder(order)\n                return return_tickets(file_path, order_identifier)\n        else:\n            return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()\n    else:\n        return ForbiddenError({'source': ''}, 'Authentication Required to access ticket').respond()\n\n\n@ticket_blueprint.route('/orders/invoices/<string:order_identifier>')\n@jwt_required()\ndef order_invoices(order_identifier):\n    if current_user:\n        try:\n            order = Order.query.filter_by(identifier=order_identifier).first()\n            user_id = order.user.id\n        except NoResultFound:\n            return NotFoundError({'source': ''}, 'Order Invoice not found').respond()\n        if current_user.id == user_id:\n            key = UPLOAD_PATHS['pdf']['order'].format(identifier=order_identifier)\n            file_path = '../generated/invoices/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'\n            response = make_response(send_file(file_path))\n            response.headers['Content-Disposition'] = 'attachment; filename=invoice-%s.zip' % order_identifier\n            return response\n        else:\n            return ForbiddenError({'source': ''}, 'Unauthorized Access').respond()\n    else:\n        return ForbiddenError({'source': ''}, 'Authentication Required to access Invoice').respond()\n", "path": "app/api/auth.py"}]}