We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Disallow creating users with same email.
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
Right now we can create users with the same email. If we soft-delete a user account and try to create an account with the same email again, the server allows creating it but sends HTTP 500 when doing so since it voilates the unique constraint in the db.

![image](https://user-images.githubusercontent.com/21277837/43689278-8f3072b2-9915-11e8-94c9-56fce267f5fc.png)


--- 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/users.py`
Content:
```
1 import base64
2 
3 from flask import Blueprint, request, jsonify, abort, make_response
4 from flask_jwt import current_identity as current_user
5 from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship
6 from sqlalchemy.orm.exc import NoResultFound
7 import urllib.error
8 
9 from app import get_settings
10 from app.api.bootstrap import api
11 from app.api.helpers.db import safe_query, get_count
12 from app.api.helpers.exceptions import ConflictException, UnprocessableEntity, ForbiddenException
13 from app.api.helpers.files import create_save_image_sizes, make_frontend_url
14 from app.api.helpers.mail import send_email_confirmation, send_email_change_user_email, send_email_with_action
15 from app.api.helpers.permission_manager import has_access
16 from app.api.helpers.permissions import is_user_itself
17 from app.api.helpers.utilities import get_serializer, str_generator
18 from app.api.schema.users import UserSchema, UserSchemaPublic
19 from app.models import db
20 from app.models.access_code import AccessCode
21 from app.models.discount_code import DiscountCode
22 from app.models.email_notification import EmailNotification
23 from app.models.event_invoice import EventInvoice
24 from app.models.feedback import Feedback
25 from app.models.mail import USER_REGISTER_WITH_PASSWORD
26 from app.models.notification import Notification
27 from app.models.session import Session
28 from app.models.speaker import Speaker
29 from app.models.ticket_holder import TicketHolder
30 from app.models.user import User
31 from app.models.users_events_role import UsersEventsRoles
32 
33 user_misc_routes = Blueprint('user_misc', __name__, url_prefix='/v1')
34 
35 
36 class UserList(ResourceList):
37     """
38     List and create Users
39     """
40     def before_create_object(self, data, view_kwargs):
41         """
42         method to check if there is an existing user with same email which is received in data to create a new user
43         :param data:
44         :param view_kwargs:
45         :return:
46         """
47         if db.session.query(User.id).filter_by(email=data['email'], deleted_at=None).scalar() is not None:
48             raise ConflictException({'pointer': '/data/attributes/email'}, "Email already exists")
49 
50     def after_create_object(self, user, data, view_kwargs):
51         """
52         method to send-
53         email notification
54         mail link for register verification
55         add image urls
56         :param user:
57         :param data:
58         :param view_kwargs:
59         :return:
60         """
61         s = get_serializer()
62         hash = str(base64.b64encode(str(s.dumps([user.email, str_generator()])).encode()), 'utf-8')
63         link = make_frontend_url('/verify'.format(id=user.id), {'token': hash})
64         send_email_with_action(user, USER_REGISTER_WITH_PASSWORD, app_name=get_settings()['app_name'],
65                                email=user.email)
66         send_email_confirmation(user.email, link)
67 
68         if data.get('original_image_url'):
69             try:
70                 uploaded_images = create_save_image_sizes(data['original_image_url'], 'speaker-image', user.id)
71             except (urllib.error.HTTPError, urllib.error.URLError):
72                 raise UnprocessableEntity(
73                     {'source': 'attributes/original-image-url'}, 'Invalid Image URL'
74                 )
75             uploaded_images['small_image_url'] = uploaded_images['thumbnail_image_url']
76             del uploaded_images['large_image_url']
77             self.session.query(User).filter_by(id=user.id).update(uploaded_images)
78 
79     decorators = (api.has_permission('is_admin', methods="GET"),)
80     schema = UserSchema
81     data_layer = {'session': db.session,
82                   'model': User,
83                   'methods': {
84                       'before_create_object': before_create_object,
85                       'after_create_object': after_create_object
86                   }}
87 
88 
89 class UserDetail(ResourceDetail):
90     """
91     User detail by id
92     """
93     def before_get(self, args, kwargs):
94 
95         if current_user.is_admin or current_user.is_super_admin or current_user:
96             self.schema = UserSchema
97         else:
98             self.schema = UserSchemaPublic
99 
100     def before_get_object(self, view_kwargs):
101         """
102         before get method for user object
103         :param view_kwargs:
104         :return:
105         """
106         if view_kwargs.get('notification_id') is not None:
107             notification = safe_query(self, Notification, 'id', view_kwargs['notification_id'], 'notification_id')
108             if notification.user_id is not None:
109                 view_kwargs['id'] = notification.user_id
110             else:
111                 view_kwargs['id'] = None
112 
113         if view_kwargs.get('feedback_id') is not None:
114             print(view_kwargs['feedback_id'])
115             feedback = safe_query(self, Feedback, 'id', view_kwargs['feedback_id'], 'feedback_id')
116             if feedback.user_id is not None:
117                 view_kwargs['id'] = feedback.user_id
118             else:
119                 view_kwargs['id'] = None
120 
121         if view_kwargs.get('attendee_id') is not None:
122             attendee = safe_query(self, TicketHolder, 'id', view_kwargs['attendee_id'], 'attendee_id')
123             if attendee.user is not None:
124                 if (not has_access('is_user_itself',
125                                    user_id=attendee.user.id) or not has_access('is_coorganizer',
126                                                                                event_id=attendee.event_id)):
127                     raise ForbiddenException({'source': ''}, 'Access Forbidden')
128                 view_kwargs['id'] = attendee.user.id
129             else:
130                 view_kwargs['id'] = None
131 
132         if view_kwargs.get('event_invoice_id') is not None:
133             event_invoice = safe_query(self, EventInvoice, 'id', view_kwargs['event_invoice_id'], 'event_invoice_id')
134             if event_invoice.user_id is not None:
135                 view_kwargs['id'] = event_invoice.user_id
136             else:
137                 view_kwargs['id'] = None
138 
139         if view_kwargs.get('users_events_role_id') is not None:
140             users_events_role = safe_query(self, UsersEventsRoles, 'id', view_kwargs['users_events_role_id'],
141                                            'users_events_role_id')
142             if users_events_role.user_id is not None:
143                 view_kwargs['id'] = users_events_role.user_id
144 
145         if view_kwargs.get('speaker_id') is not None:
146             speaker = safe_query(self, Speaker, 'id', view_kwargs['speaker_id'], 'speaker_id')
147             if speaker.user_id is not None:
148                 view_kwargs['id'] = speaker.user_id
149             else:
150                 view_kwargs['id'] = None
151 
152         if view_kwargs.get('session_id') is not None:
153             session = safe_query(self, Session, 'id', view_kwargs['session_id'], 'session_id')
154             if session.creator_id is not None:
155                 view_kwargs['id'] = session.creator_id
156             else:
157                 view_kwargs['id'] = None
158 
159         if view_kwargs.get('access_code_id') is not None:
160             access_code = safe_query(self, AccessCode, 'id', view_kwargs['access_code_id'], 'access_code_id')
161             if access_code.marketer_id is not None:
162                 view_kwargs['id'] = access_code.marketer_id
163             else:
164                 view_kwargs['id'] = None
165 
166         if view_kwargs.get('discount_code_id') is not None:
167             discount_code = safe_query(self, DiscountCode, 'id', view_kwargs['discount_code_id'], 'discount_code_id')
168             if discount_code.marketer_id is not None:
169                 view_kwargs['id'] = discount_code.marketer_id
170             else:
171                 view_kwargs['id'] = None
172 
173         if view_kwargs.get('email_notification_id') is not None:
174             email_notification = safe_query(self, EmailNotification, 'id', view_kwargs['email_notification_id'],
175                                             'email_notification_id')
176             if email_notification.user_id is not None:
177                 view_kwargs['id'] = email_notification.user_id
178             else:
179                 view_kwargs['id'] = None
180 
181     def before_update_object(self, user, data, view_kwargs):
182         if data.get('original_image_url') and data['original_image_url'] != user.original_image_url:
183             try:
184                 uploaded_images = create_save_image_sizes(data['original_image_url'], 'speaker-image', user.id)
185             except (urllib.error.HTTPError, urllib.error.URLError):
186                 raise UnprocessableEntity(
187                     {'source': 'attributes/original-image-url'}, 'Invalid Image URL'
188                 )
189             data['original_image_url'] = uploaded_images['original_image_url']
190             data['small_image_url'] = uploaded_images['thumbnail_image_url']
191             data['thumbnail_image_url'] = uploaded_images['thumbnail_image_url']
192             data['icon_image_url'] = uploaded_images['icon_image_url']
193 
194         if data.get('email') and data['email'] != user.email:
195             try:
196                 db.session.query(User).filter_by(email=data['email']).one()
197             except NoResultFound:
198                 view_kwargs['email_changed'] = user.email
199             else:
200                 raise ConflictException({'pointer': '/data/attributes/email'}, "Email already exists")
201 
202         if has_access('is_super_admin') and data.get('is_admin') != user.is_admin:
203             user.is_admin = not user.is_admin
204 
205         if has_access('is_admin') and data.get('is_sales_admin') != user.is_sales_admin:
206             user.is_sales_admin = not user.is_sales_admin
207 
208         if has_access('is_admin') and data.get('is_marketer') != user.is_marketer:
209             user.is_marketer = not user.is_marketer
210 
211     def after_update_object(self, user, data, view_kwargs):
212         """
213         method to mail user about email change
214         :param user:
215         :param data:
216         :param view_kwargs:
217         :return:
218         """
219         if view_kwargs.get('email_changed'):
220             send_email_change_user_email(user, view_kwargs.get('email_changed'))
221 
222     decorators = (api.has_permission('is_user_itself', fetch="user_id,id", fetch_as="user_id",
223                   model=[Notification, Feedback, UsersEventsRoles, Session, EventInvoice, AccessCode,
224                          DiscountCode, EmailNotification, Speaker, User],
225                   fetch_key_url="notification_id, feedback_id, users_events_role_id, session_id, \
226                   event_invoice_id, access_code_id, discount_code_id, email_notification_id, speaker_id, id",
227                   leave_if=lambda a: a.get('attendee_id')), )
228     schema = UserSchema
229     data_layer = {'session': db.session,
230                   'model': User,
231                   'methods': {
232                       'before_get_object': before_get_object,
233                       'before_update_object': before_update_object,
234                       'after_update_object': after_update_object
235                   }}
236 
237 
238 class UserRelationship(ResourceRelationship):
239     """
240     User Relationship
241     """
242     decorators = (is_user_itself, )
243     schema = UserSchema
244     data_layer = {'session': db.session,
245                   'model': User}
246 
247 
248 @user_misc_routes.route('/users/checkEmail', methods=['POST'])
249 def is_email_available():
250     email = request.json.get('email', None)
251     if email:
252         if get_count(db.session.query(User).filter_by(email=email)):
253             return jsonify(
254                 result="False"
255             )
256         else:
257             return jsonify(
258                 result="True"
259             )
260     else:
261         abort(
262             make_response(jsonify(error="Email field missing"), 422)
263         )
264
```
--- 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/users.py b/app/api/users.py
--- a/app/api/users.py
+++ b/app/api/users.py
@@ -44,7 +44,7 @@
         :param view_kwargs:
         :return:
         """
-        if db.session.query(User.id).filter_by(email=data['email'], deleted_at=None).scalar() is not None:
+        if db.session.query(User.id).filter_by(email=data['email']).scalar() is not None:
             raise ConflictException({'pointer': '/data/attributes/email'}, "Email already exists")
 
     def after_create_object(self, user, data, view_kwargs):

{"golden_diff": "diff --git a/app/api/users.py b/app/api/users.py\n--- a/app/api/users.py\n+++ b/app/api/users.py\n@@ -44,7 +44,7 @@\n         :param view_kwargs:\n         :return:\n         \"\"\"\n-        if db.session.query(User.id).filter_by(email=data['email'], deleted_at=None).scalar() is not None:\n+        if db.session.query(User.id).filter_by(email=data['email']).scalar() is not None:\n             raise ConflictException({'pointer': '/data/attributes/email'}, \"Email already exists\")\n \n     def after_create_object(self, user, data, view_kwargs):\n", "issue": "Disallow creating users with same email.\n**Is your feature request related to a problem? Please describe.**\r\n<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->\r\nRight now we can create users with the same email. If we soft-delete a user account and try to create an account with the same email again, the server allows creating it but sends HTTP 500 when doing so since it voilates the unique constraint in the db.\r\n\r\n![image](https://user-images.githubusercontent.com/21277837/43689278-8f3072b2-9915-11e8-94c9-56fce267f5fc.png)\r\n\n", "before_files": [{"content": "import base64\n\nfrom flask import Blueprint, request, jsonify, abort, make_response\nfrom flask_jwt import current_identity as current_user\nfrom flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship\nfrom sqlalchemy.orm.exc import NoResultFound\nimport urllib.error\n\nfrom app import get_settings\nfrom app.api.bootstrap import api\nfrom app.api.helpers.db import safe_query, get_count\nfrom app.api.helpers.exceptions import ConflictException, UnprocessableEntity, ForbiddenException\nfrom app.api.helpers.files import create_save_image_sizes, make_frontend_url\nfrom app.api.helpers.mail import send_email_confirmation, send_email_change_user_email, send_email_with_action\nfrom app.api.helpers.permission_manager import has_access\nfrom app.api.helpers.permissions import is_user_itself\nfrom app.api.helpers.utilities import get_serializer, str_generator\nfrom app.api.schema.users import UserSchema, UserSchemaPublic\nfrom app.models import db\nfrom app.models.access_code import AccessCode\nfrom app.models.discount_code import DiscountCode\nfrom app.models.email_notification import EmailNotification\nfrom app.models.event_invoice import EventInvoice\nfrom app.models.feedback import Feedback\nfrom app.models.mail import USER_REGISTER_WITH_PASSWORD\nfrom app.models.notification import Notification\nfrom app.models.session import Session\nfrom app.models.speaker import Speaker\nfrom app.models.ticket_holder import TicketHolder\nfrom app.models.user import User\nfrom app.models.users_events_role import UsersEventsRoles\n\nuser_misc_routes = Blueprint('user_misc', __name__, url_prefix='/v1')\n\n\nclass UserList(ResourceList):\n    \"\"\"\n    List and create Users\n    \"\"\"\n    def before_create_object(self, data, view_kwargs):\n        \"\"\"\n        method to check if there is an existing user with same email which is received in data to create a new user\n        :param data:\n        :param view_kwargs:\n        :return:\n        \"\"\"\n        if db.session.query(User.id).filter_by(email=data['email'], deleted_at=None).scalar() is not None:\n            raise ConflictException({'pointer': '/data/attributes/email'}, \"Email already exists\")\n\n    def after_create_object(self, user, data, view_kwargs):\n        \"\"\"\n        method to send-\n        email notification\n        mail link for register verification\n        add image urls\n        :param user:\n        :param data:\n        :param view_kwargs:\n        :return:\n        \"\"\"\n        s = get_serializer()\n        hash = str(base64.b64encode(str(s.dumps([user.email, str_generator()])).encode()), 'utf-8')\n        link = make_frontend_url('/verify'.format(id=user.id), {'token': hash})\n        send_email_with_action(user, USER_REGISTER_WITH_PASSWORD, app_name=get_settings()['app_name'],\n                               email=user.email)\n        send_email_confirmation(user.email, link)\n\n        if data.get('original_image_url'):\n            try:\n                uploaded_images = create_save_image_sizes(data['original_image_url'], 'speaker-image', user.id)\n            except (urllib.error.HTTPError, urllib.error.URLError):\n                raise UnprocessableEntity(\n                    {'source': 'attributes/original-image-url'}, 'Invalid Image URL'\n                )\n            uploaded_images['small_image_url'] = uploaded_images['thumbnail_image_url']\n            del uploaded_images['large_image_url']\n            self.session.query(User).filter_by(id=user.id).update(uploaded_images)\n\n    decorators = (api.has_permission('is_admin', methods=\"GET\"),)\n    schema = UserSchema\n    data_layer = {'session': db.session,\n                  'model': User,\n                  'methods': {\n                      'before_create_object': before_create_object,\n                      'after_create_object': after_create_object\n                  }}\n\n\nclass UserDetail(ResourceDetail):\n    \"\"\"\n    User detail by id\n    \"\"\"\n    def before_get(self, args, kwargs):\n\n        if current_user.is_admin or current_user.is_super_admin or current_user:\n            self.schema = UserSchema\n        else:\n            self.schema = UserSchemaPublic\n\n    def before_get_object(self, view_kwargs):\n        \"\"\"\n        before get method for user object\n        :param view_kwargs:\n        :return:\n        \"\"\"\n        if view_kwargs.get('notification_id') is not None:\n            notification = safe_query(self, Notification, 'id', view_kwargs['notification_id'], 'notification_id')\n            if notification.user_id is not None:\n                view_kwargs['id'] = notification.user_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('feedback_id') is not None:\n            print(view_kwargs['feedback_id'])\n            feedback = safe_query(self, Feedback, 'id', view_kwargs['feedback_id'], 'feedback_id')\n            if feedback.user_id is not None:\n                view_kwargs['id'] = feedback.user_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('attendee_id') is not None:\n            attendee = safe_query(self, TicketHolder, 'id', view_kwargs['attendee_id'], 'attendee_id')\n            if attendee.user is not None:\n                if (not has_access('is_user_itself',\n                                   user_id=attendee.user.id) or not has_access('is_coorganizer',\n                                                                               event_id=attendee.event_id)):\n                    raise ForbiddenException({'source': ''}, 'Access Forbidden')\n                view_kwargs['id'] = attendee.user.id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('event_invoice_id') is not None:\n            event_invoice = safe_query(self, EventInvoice, 'id', view_kwargs['event_invoice_id'], 'event_invoice_id')\n            if event_invoice.user_id is not None:\n                view_kwargs['id'] = event_invoice.user_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('users_events_role_id') is not None:\n            users_events_role = safe_query(self, UsersEventsRoles, 'id', view_kwargs['users_events_role_id'],\n                                           'users_events_role_id')\n            if users_events_role.user_id is not None:\n                view_kwargs['id'] = users_events_role.user_id\n\n        if view_kwargs.get('speaker_id') is not None:\n            speaker = safe_query(self, Speaker, 'id', view_kwargs['speaker_id'], 'speaker_id')\n            if speaker.user_id is not None:\n                view_kwargs['id'] = speaker.user_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('session_id') is not None:\n            session = safe_query(self, Session, 'id', view_kwargs['session_id'], 'session_id')\n            if session.creator_id is not None:\n                view_kwargs['id'] = session.creator_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('access_code_id') is not None:\n            access_code = safe_query(self, AccessCode, 'id', view_kwargs['access_code_id'], 'access_code_id')\n            if access_code.marketer_id is not None:\n                view_kwargs['id'] = access_code.marketer_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('discount_code_id') is not None:\n            discount_code = safe_query(self, DiscountCode, 'id', view_kwargs['discount_code_id'], 'discount_code_id')\n            if discount_code.marketer_id is not None:\n                view_kwargs['id'] = discount_code.marketer_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('email_notification_id') is not None:\n            email_notification = safe_query(self, EmailNotification, 'id', view_kwargs['email_notification_id'],\n                                            'email_notification_id')\n            if email_notification.user_id is not None:\n                view_kwargs['id'] = email_notification.user_id\n            else:\n                view_kwargs['id'] = None\n\n    def before_update_object(self, user, data, view_kwargs):\n        if data.get('original_image_url') and data['original_image_url'] != user.original_image_url:\n            try:\n                uploaded_images = create_save_image_sizes(data['original_image_url'], 'speaker-image', user.id)\n            except (urllib.error.HTTPError, urllib.error.URLError):\n                raise UnprocessableEntity(\n                    {'source': 'attributes/original-image-url'}, 'Invalid Image URL'\n                )\n            data['original_image_url'] = uploaded_images['original_image_url']\n            data['small_image_url'] = uploaded_images['thumbnail_image_url']\n            data['thumbnail_image_url'] = uploaded_images['thumbnail_image_url']\n            data['icon_image_url'] = uploaded_images['icon_image_url']\n\n        if data.get('email') and data['email'] != user.email:\n            try:\n                db.session.query(User).filter_by(email=data['email']).one()\n            except NoResultFound:\n                view_kwargs['email_changed'] = user.email\n            else:\n                raise ConflictException({'pointer': '/data/attributes/email'}, \"Email already exists\")\n\n        if has_access('is_super_admin') and data.get('is_admin') != user.is_admin:\n            user.is_admin = not user.is_admin\n\n        if has_access('is_admin') and data.get('is_sales_admin') != user.is_sales_admin:\n            user.is_sales_admin = not user.is_sales_admin\n\n        if has_access('is_admin') and data.get('is_marketer') != user.is_marketer:\n            user.is_marketer = not user.is_marketer\n\n    def after_update_object(self, user, data, view_kwargs):\n        \"\"\"\n        method to mail user about email change\n        :param user:\n        :param data:\n        :param view_kwargs:\n        :return:\n        \"\"\"\n        if view_kwargs.get('email_changed'):\n            send_email_change_user_email(user, view_kwargs.get('email_changed'))\n\n    decorators = (api.has_permission('is_user_itself', fetch=\"user_id,id\", fetch_as=\"user_id\",\n                  model=[Notification, Feedback, UsersEventsRoles, Session, EventInvoice, AccessCode,\n                         DiscountCode, EmailNotification, Speaker, User],\n                  fetch_key_url=\"notification_id, feedback_id, users_events_role_id, session_id, \\\n                  event_invoice_id, access_code_id, discount_code_id, email_notification_id, speaker_id, id\",\n                  leave_if=lambda a: a.get('attendee_id')), )\n    schema = UserSchema\n    data_layer = {'session': db.session,\n                  'model': User,\n                  'methods': {\n                      'before_get_object': before_get_object,\n                      'before_update_object': before_update_object,\n                      'after_update_object': after_update_object\n                  }}\n\n\nclass UserRelationship(ResourceRelationship):\n    \"\"\"\n    User Relationship\n    \"\"\"\n    decorators = (is_user_itself, )\n    schema = UserSchema\n    data_layer = {'session': db.session,\n                  'model': User}\n\n\n@user_misc_routes.route('/users/checkEmail', methods=['POST'])\ndef is_email_available():\n    email = request.json.get('email', None)\n    if email:\n        if get_count(db.session.query(User).filter_by(email=email)):\n            return jsonify(\n                result=\"False\"\n            )\n        else:\n            return jsonify(\n                result=\"True\"\n            )\n    else:\n        abort(\n            make_response(jsonify(error=\"Email field missing\"), 422)\n        )\n", "path": "app/api/users.py"}], "after_files": [{"content": "import base64\n\nfrom flask import Blueprint, request, jsonify, abort, make_response\nfrom flask_jwt import current_identity as current_user\nfrom flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship\nfrom sqlalchemy.orm.exc import NoResultFound\nimport urllib.error\n\nfrom app import get_settings\nfrom app.api.bootstrap import api\nfrom app.api.helpers.db import safe_query, get_count\nfrom app.api.helpers.exceptions import ConflictException, UnprocessableEntity, ForbiddenException\nfrom app.api.helpers.files import create_save_image_sizes, make_frontend_url\nfrom app.api.helpers.mail import send_email_confirmation, send_email_change_user_email, send_email_with_action\nfrom app.api.helpers.permission_manager import has_access\nfrom app.api.helpers.permissions import is_user_itself\nfrom app.api.helpers.utilities import get_serializer, str_generator\nfrom app.api.schema.users import UserSchema, UserSchemaPublic\nfrom app.models import db\nfrom app.models.access_code import AccessCode\nfrom app.models.discount_code import DiscountCode\nfrom app.models.email_notification import EmailNotification\nfrom app.models.event_invoice import EventInvoice\nfrom app.models.feedback import Feedback\nfrom app.models.mail import USER_REGISTER_WITH_PASSWORD\nfrom app.models.notification import Notification\nfrom app.models.session import Session\nfrom app.models.speaker import Speaker\nfrom app.models.ticket_holder import TicketHolder\nfrom app.models.user import User\nfrom app.models.users_events_role import UsersEventsRoles\n\nuser_misc_routes = Blueprint('user_misc', __name__, url_prefix='/v1')\n\n\nclass UserList(ResourceList):\n    \"\"\"\n    List and create Users\n    \"\"\"\n    def before_create_object(self, data, view_kwargs):\n        \"\"\"\n        method to check if there is an existing user with same email which is received in data to create a new user\n        :param data:\n        :param view_kwargs:\n        :return:\n        \"\"\"\n        if db.session.query(User.id).filter_by(email=data['email']).scalar() is not None:\n            raise ConflictException({'pointer': '/data/attributes/email'}, \"Email already exists\")\n\n    def after_create_object(self, user, data, view_kwargs):\n        \"\"\"\n        method to send-\n        email notification\n        mail link for register verification\n        add image urls\n        :param user:\n        :param data:\n        :param view_kwargs:\n        :return:\n        \"\"\"\n        s = get_serializer()\n        hash = str(base64.b64encode(str(s.dumps([user.email, str_generator()])).encode()), 'utf-8')\n        link = make_frontend_url('/verify'.format(id=user.id), {'token': hash})\n        send_email_with_action(user, USER_REGISTER_WITH_PASSWORD, app_name=get_settings()['app_name'],\n                               email=user.email)\n        send_email_confirmation(user.email, link)\n\n        if data.get('original_image_url'):\n            try:\n                uploaded_images = create_save_image_sizes(data['original_image_url'], 'speaker-image', user.id)\n            except (urllib.error.HTTPError, urllib.error.URLError):\n                raise UnprocessableEntity(\n                    {'source': 'attributes/original-image-url'}, 'Invalid Image URL'\n                )\n            uploaded_images['small_image_url'] = uploaded_images['thumbnail_image_url']\n            del uploaded_images['large_image_url']\n            self.session.query(User).filter_by(id=user.id).update(uploaded_images)\n\n    decorators = (api.has_permission('is_admin', methods=\"GET\"),)\n    schema = UserSchema\n    data_layer = {'session': db.session,\n                  'model': User,\n                  'methods': {\n                      'before_create_object': before_create_object,\n                      'after_create_object': after_create_object\n                  }}\n\n\nclass UserDetail(ResourceDetail):\n    \"\"\"\n    User detail by id\n    \"\"\"\n    def before_get(self, args, kwargs):\n\n        if current_user.is_admin or current_user.is_super_admin or current_user:\n            self.schema = UserSchema\n        else:\n            self.schema = UserSchemaPublic\n\n    def before_get_object(self, view_kwargs):\n        \"\"\"\n        before get method for user object\n        :param view_kwargs:\n        :return:\n        \"\"\"\n        if view_kwargs.get('notification_id') is not None:\n            notification = safe_query(self, Notification, 'id', view_kwargs['notification_id'], 'notification_id')\n            if notification.user_id is not None:\n                view_kwargs['id'] = notification.user_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('feedback_id') is not None:\n            print(view_kwargs['feedback_id'])\n            feedback = safe_query(self, Feedback, 'id', view_kwargs['feedback_id'], 'feedback_id')\n            if feedback.user_id is not None:\n                view_kwargs['id'] = feedback.user_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('attendee_id') is not None:\n            attendee = safe_query(self, TicketHolder, 'id', view_kwargs['attendee_id'], 'attendee_id')\n            if attendee.user is not None:\n                if (not has_access('is_user_itself',\n                                   user_id=attendee.user.id) or not has_access('is_coorganizer',\n                                                                               event_id=attendee.event_id)):\n                    raise ForbiddenException({'source': ''}, 'Access Forbidden')\n                view_kwargs['id'] = attendee.user.id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('event_invoice_id') is not None:\n            event_invoice = safe_query(self, EventInvoice, 'id', view_kwargs['event_invoice_id'], 'event_invoice_id')\n            if event_invoice.user_id is not None:\n                view_kwargs['id'] = event_invoice.user_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('users_events_role_id') is not None:\n            users_events_role = safe_query(self, UsersEventsRoles, 'id', view_kwargs['users_events_role_id'],\n                                           'users_events_role_id')\n            if users_events_role.user_id is not None:\n                view_kwargs['id'] = users_events_role.user_id\n\n        if view_kwargs.get('speaker_id') is not None:\n            speaker = safe_query(self, Speaker, 'id', view_kwargs['speaker_id'], 'speaker_id')\n            if speaker.user_id is not None:\n                view_kwargs['id'] = speaker.user_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('session_id') is not None:\n            session = safe_query(self, Session, 'id', view_kwargs['session_id'], 'session_id')\n            if session.creator_id is not None:\n                view_kwargs['id'] = session.creator_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('access_code_id') is not None:\n            access_code = safe_query(self, AccessCode, 'id', view_kwargs['access_code_id'], 'access_code_id')\n            if access_code.marketer_id is not None:\n                view_kwargs['id'] = access_code.marketer_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('discount_code_id') is not None:\n            discount_code = safe_query(self, DiscountCode, 'id', view_kwargs['discount_code_id'], 'discount_code_id')\n            if discount_code.marketer_id is not None:\n                view_kwargs['id'] = discount_code.marketer_id\n            else:\n                view_kwargs['id'] = None\n\n        if view_kwargs.get('email_notification_id') is not None:\n            email_notification = safe_query(self, EmailNotification, 'id', view_kwargs['email_notification_id'],\n                                            'email_notification_id')\n            if email_notification.user_id is not None:\n                view_kwargs['id'] = email_notification.user_id\n            else:\n                view_kwargs['id'] = None\n\n    def before_update_object(self, user, data, view_kwargs):\n        if data.get('original_image_url') and data['original_image_url'] != user.original_image_url:\n            try:\n                uploaded_images = create_save_image_sizes(data['original_image_url'], 'speaker-image', user.id)\n            except (urllib.error.HTTPError, urllib.error.URLError):\n                raise UnprocessableEntity(\n                    {'source': 'attributes/original-image-url'}, 'Invalid Image URL'\n                )\n            data['original_image_url'] = uploaded_images['original_image_url']\n            data['small_image_url'] = uploaded_images['thumbnail_image_url']\n            data['thumbnail_image_url'] = uploaded_images['thumbnail_image_url']\n            data['icon_image_url'] = uploaded_images['icon_image_url']\n\n        if data.get('email') and data['email'] != user.email:\n            try:\n                db.session.query(User).filter_by(email=data['email']).one()\n            except NoResultFound:\n                view_kwargs['email_changed'] = user.email\n            else:\n                raise ConflictException({'pointer': '/data/attributes/email'}, \"Email already exists\")\n\n        if has_access('is_super_admin') and data.get('is_admin') != user.is_admin:\n            user.is_admin = not user.is_admin\n\n        if has_access('is_admin') and data.get('is_sales_admin') != user.is_sales_admin:\n            user.is_sales_admin = not user.is_sales_admin\n\n        if has_access('is_admin') and data.get('is_marketer') != user.is_marketer:\n            user.is_marketer = not user.is_marketer\n\n    def after_update_object(self, user, data, view_kwargs):\n        \"\"\"\n        method to mail user about email change\n        :param user:\n        :param data:\n        :param view_kwargs:\n        :return:\n        \"\"\"\n        if view_kwargs.get('email_changed'):\n            send_email_change_user_email(user, view_kwargs.get('email_changed'))\n\n    decorators = (api.has_permission('is_user_itself', fetch=\"user_id,id\", fetch_as=\"user_id\",\n                  model=[Notification, Feedback, UsersEventsRoles, Session, EventInvoice, AccessCode,\n                         DiscountCode, EmailNotification, Speaker, User],\n                  fetch_key_url=\"notification_id, feedback_id, users_events_role_id, session_id, \\\n                  event_invoice_id, access_code_id, discount_code_id, email_notification_id, speaker_id, id\",\n                  leave_if=lambda a: a.get('attendee_id')), )\n    schema = UserSchema\n    data_layer = {'session': db.session,\n                  'model': User,\n                  'methods': {\n                      'before_get_object': before_get_object,\n                      'before_update_object': before_update_object,\n                      'after_update_object': after_update_object\n                  }}\n\n\nclass UserRelationship(ResourceRelationship):\n    \"\"\"\n    User Relationship\n    \"\"\"\n    decorators = (is_user_itself, )\n    schema = UserSchema\n    data_layer = {'session': db.session,\n                  'model': User}\n\n\n@user_misc_routes.route('/users/checkEmail', methods=['POST'])\ndef is_email_available():\n    email = request.json.get('email', None)\n    if email:\n        if get_count(db.session.query(User).filter_by(email=email)):\n            return jsonify(\n                result=\"False\"\n            )\n        else:\n            return jsonify(\n                result=\"True\"\n            )\n    else:\n        abort(\n            make_response(jsonify(error=\"Email field missing\"), 422)\n        )\n", "path": "app/api/users.py"}]}