Repository: fossasia/open-event-server

Issue:
Allow checking whether an email is registered
**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 [...] -->
Users API should allow checking whether an email is registered.

**Describe the solution you'd like**
<!-- A clear and concise description of what you want to happen. -->
A POST request requiring only an email address should respond whether the email is registered or not.

**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->
Orga App issue: [#971](https://github.com/fossasia/open-event-orga-app/issues/971)


Discussion:
The user api schema has already an attribute called  `"is-verified"` this is essentially what you're looking for.

![image](https://user-images.githubusercontent.com/2415206/42131259-a2db503a-7cfe-11e8-916a-f44f70916615.png)

@Kreijstal No, what he is saying is an endpoint to check if that particular email-id is already registered or not. Just as the username is checked for availability when you type it on other websites.
ah, e-mail in open-event is already unique so the server won't allow it to register to more than user, because in open-event there are no usernames, I'd say that's a frontend issue.
No need for post request, use this route
GET /v1/users?filter=[{"name":"email","op":"eq","val":(value of the e-mail address you want to check)}]
> GET /v1/users?filter=[{"name":"email","op":"eq","val":(value of the e-mail address you want to check)}]

This will require admin access. How will the FE/Android app use it ?
@Kreijstal 
See probably you guys are not familiar with the requirement. This is a requirement in the orga app. 
What we want to do in the app is that when the user opens the app, he/she will be presented with a screen asking for the email address. Now the app will check if the email is registered or not.
 
1. If registered, then we will present the user with a password field
2. If not registered, then the user will be asked to register.

When no one has logged in,we cannot use /v1/users since it requires admin access. We have to make this endpoint public i.e. it shouldn't even require a JWT token just like the endpoint for registering the user. Create a new endpoint for this which accepts the email and sends the response as registered or not. 

@mayank8318 @Kreijstal 

Ok I will work on this

Resolving patch:
diff --git a/app/__init__.py b/app/__init__.py
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -122,6 +122,7 @@ def create_app():
         from app.api.auth import auth_routes
         from app.api.admin_statistics_api.events import event_statistics
         from app.api.event_copy import event_copy
+        from app.api.users import user_misc_routes
 
         app.register_blueprint(api_v1)
         app.register_blueprint(event_copy)
@@ -131,6 +132,7 @@ def create_app():
         app.register_blueprint(celery_routes)
         app.register_blueprint(auth_routes)
         app.register_blueprint(event_statistics)
+        app.register_blueprint(user_misc_routes)
 
     sa.orm.configure_mappers()
 
diff --git a/app/api/users.py b/app/api/users.py
--- a/app/api/users.py
+++ b/app/api/users.py
@@ -1,12 +1,17 @@
 import base64
 
-from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship
+from flask import Blueprint, request, jsonify, abort, make_response
 from flask_jwt import current_identity as current_user
+from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship
 
 from app import get_settings
 from app.api.bootstrap import api
+from app.api.helpers.db import safe_query, get_count
+from app.api.helpers.exceptions import ConflictException
+from app.api.helpers.exceptions import ForbiddenException
 from app.api.helpers.files import create_save_image_sizes, make_frontend_url
 from app.api.helpers.mail import send_email_confirmation, send_email_change_user_email, send_email_with_action
+from app.api.helpers.permission_manager import has_access
 from app.api.helpers.permissions import is_user_itself
 from app.api.helpers.utilities import get_serializer, str_generator
 from app.api.schema.users import UserSchema, UserSchemaPublic
@@ -15,18 +20,16 @@
 from app.models.discount_code import DiscountCode
 from app.models.email_notification import EmailNotification
 from app.models.event_invoice import EventInvoice
+from app.models.feedback import Feedback
 from app.models.mail import USER_REGISTER_WITH_PASSWORD
 from app.models.notification import Notification
-from app.models.feedback import Feedback
-from app.models.speaker import Speaker
 from app.models.session import Session
-from app.api.helpers.exceptions import ConflictException
-from app.api.helpers.db import safe_query
+from app.models.speaker import Speaker
+from app.models.ticket_holder import TicketHolder
 from app.models.user import User
 from app.models.users_events_role import UsersEventsRoles
-from app.models.ticket_holder import TicketHolder
-from app.api.helpers.exceptions import ForbiddenException
-from app.api.helpers.permission_manager import has_access
+
+user_misc_routes = Blueprint('user_misc', __name__, url_prefix='/v1')
 
 
 class UserList(ResourceList):
@@ -215,3 +218,21 @@ class UserRelationship(ResourceRelationship):
     schema = UserSchema
     data_layer = {'session': db.session,
                   'model': User}
+
+
+@user_misc_routes.route('/users/checkEmail', methods=['POST'])
+def is_email_available():
+    email = request.json.get('email', None)
+    if email:
+        if get_count(db.session.query(User).filter_by(email=email)):
+            return jsonify(
+                result="False"
+            )
+        else:
+            return jsonify(
+                result="True"
+            )
+    else:
+        abort(
+            make_response(jsonify(error="Email field missing"), 422)
+        )


Test patch:
diff --git a/tests/hook_main.py b/tests/hook_main.py
--- a/tests/hook_main.py
+++ b/tests/hook_main.py
@@ -1,5 +1,6 @@
-import sys
 import os.path as path
+import sys
+
 import dredd_hooks as hooks
 import requests
 
@@ -276,6 +277,16 @@ def user_speaker(transaction):
         db.session.commit()
 
 
+@hooks.before("Users > Check if the email is available > Check if email is available")
+def user_check_email(transaction):
+    """
+    POST /users/checkEmail
+    :param transaction:
+    :return:
+    """
+    transaction['skip'] = True
+
+
 # ------------------------- Events -------------------------
 @hooks.before("Events > Events Collection > List All Events")
 def event_get_list(transaction):