about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-05-30 16:13:04 -0500
committerFrederick Muriuki Muriithi2024-06-03 10:08:23 -0500
commitffe9e7104ba83b73d78d66de2d29ad4ace6de2da (patch)
tree82dd7cf2265c11d6d0e7714b9680ab5bec92277a
parentc462653f53858359a81cfed561f1622d7e63102b (diff)
downloadgn-auth-ffe9e7104ba83b73d78d66de2d29ad4ace6de2da.tar.gz
Provide endpoint for verification and do verification
-rw-r--r--gn_auth/auth/authorisation/users/views.py54
-rw-r--r--gn_auth/auth/errors.py3
-rw-r--r--gn_auth/templates/emails/verify-email.html27
-rw-r--r--gn_auth/templates/emails/verify-email.txt2
4 files changed, 60 insertions, 26 deletions
diff --git a/gn_auth/auth/authorisation/users/views.py b/gn_auth/auth/authorisation/users/views.py
index 8919a6d..638f0df 100644
--- a/gn_auth/auth/authorisation/users/views.py
+++ b/gn_auth/auth/authorisation/users/views.py
@@ -25,11 +25,16 @@ from gn_auth.auth.authorisation.resources.models import (
     user_resources as _user_resources)
 from gn_auth.auth.authorisation.roles.models import (
     assign_default_roles, user_roles as _user_roles)
-from gn_auth.auth.errors import (
-    NotFoundError, UsernameError, PasswordError, UserRegistrationError)
 from gn_auth.auth.authorisation.resources.groups.models import (
     user_group as _user_group)
 
+from gn_auth.auth.errors import (
+    NotFoundError,
+    UsernameError,
+    PasswordError,
+    UserVerificationError,
+    UserRegistrationError)
+
 from gn_auth.auth.authentication.oauth2.resource_server import require_oauth
 from gn_auth.auth.authentication.users import User, save_user, set_user_password
 from gn_auth.auth.authentication.oauth2.models.oauth2token import (
@@ -169,6 +174,51 @@ def register_user() -> Response:
     raise Exception(
         "unknown_error", "The system experienced an unexpected error.")
 
+def delete_verification_code(cursor, code: str):
+    """Delete verification code from db."""
+    cursor.execute("DELETE FROM user_verification_codes "
+                   "WHERE code=:code",
+                   {"code": code})
+
+@users.route("/verify", methods=["GET", "POST"])
+def verify_user():
+    """Verify users are not bots."""
+    code = request.args.get("verificationcode",
+                            request.form.get("verificationcode",
+                                             "nosuchcode"))
+    with (db.connection(current_app.config["AUTH_DB"]) as conn,
+          db.cursor(conn) as cursor):
+        cursor.execute("SELECT * FROM user_verification_codes "
+                       "WHERE code=:code",
+                       {"code": code})
+        results = tuple(dict(row) for row in cursor.fetchall())
+
+        if not bool(results):
+            raise UserVerificationError(
+                "Invalid verification code: code not found.")
+
+        if len(results) > 1:
+            delete_verification_code(cursor, code)
+            raise UserVerificationError(
+                "Invalid verification code: code is duplicated.")
+
+        results = results[0]
+        if (datetime.datetime.fromtimestamp(
+                int(results["expires"])) < datetime.datetime.now()):
+            delete_verification_code(cursor, code)
+            raise UserVerificationError(
+                "Invalid verification code: code has expired.")
+
+        # Code is good!
+        delete_verification_code(cursor, code)
+        cursor.execute("UPDATE users SET verified=1 WHERE user_id=:user_id",
+                       {"user_id": results["user_id"]})
+        return jsonify({
+            "status": "success",
+            "message": "User verification successful!"
+        })
+
+
 @users.route("/group", methods=["GET"])
 @require_oauth("profile group")
 def user_group() -> Response:
diff --git a/gn_auth/auth/errors.py b/gn_auth/auth/errors.py
index 60d6a22..77b73aa 100644
--- a/gn_auth/auth/errors.py
+++ b/gn_auth/auth/errors.py
@@ -15,6 +15,9 @@ class ForbiddenAccess(AuthorisationError):
 class UserRegistrationError(AuthorisationError):
     """Raised whenever a user registration fails"""
 
+class UserVerificationError(UserRegistrationError):
+    """Raised when verification of a user fails."""
+
 class NotFoundError(AuthorisationError):
     """Raised whenever we try fetching (a/an) object(s) that do(es) not exist."""
     error_code: int = 404
diff --git a/gn_auth/templates/emails/verify-email.html b/gn_auth/templates/emails/verify-email.html
index 08f1dfe..bc475c9 100644
--- a/gn_auth/templates/emails/verify-email.html
+++ b/gn_auth/templates/emails/verify-email.html
@@ -2,25 +2,6 @@
   <head>
     <meta charset="UTF-8" />
     <title>{{subject}}</title>
-    <style type="text/css">
-      .btn {
-          display: inline-block;
-          text-align: center;
-          vertical-align: center;
-          cursor: pointer;
-          border-radius: 4px;
-          background-color: #336699;
-          border-color: #357ebd;
-      }
-      .verification-code{
-          color: #3A3AFF;
-          font-weight: bolder;
-      }
-      .note {
-          font-weight: bold;
-          color: #ee55ee;
-      }
-    </style>
   </head>
   <body>
     <p>Thank you for registering an account with GeneNetwork.</p>
@@ -28,8 +9,8 @@
     <p>
       To avoid bots, we need to verify that you are an actual human. To do so,
       please
-      <a href="{{verification_uri}}/{{verification_code}}"
-         class="btn">
+      <a href="{{verification_uri}}?verificationcode={{verification_code}}"
+         style="display: inline-block;text-align: center;vertical-align: center;cursor: pointer;border-radius: 4px;background-color: #336699;border-color: #357ebd;">
         Click here
       </a>.
     </p>
@@ -38,10 +19,10 @@
       If that does not work, please log in to GeneNetwork and copy the
       verification code below when requested:<br /><br />
 
-      <span class="verification-code">{{verification_code}}</span>
+      <span style="color: #3A3AFF;font-weight: bolder;">{{verification_code}}</span>
     </p>
 
-    <p class="note">
+    <p style="font-weight: bold;color: #ee55ee;">
       Please note that the verification code will expire in
       <strong>{{expiration_minutes}}</strong> minutes after it was generated.
     </p>
diff --git a/gn_auth/templates/emails/verify-email.txt b/gn_auth/templates/emails/verify-email.txt
index 92a6435..7a39fea 100644
--- a/gn_auth/templates/emails/verify-email.txt
+++ b/gn_auth/templates/emails/verify-email.txt
@@ -3,7 +3,7 @@
 
 Thank you for registering an account with GeneNetwork.
 
-To avoid bots, we need to verify that you are an actual human. To do so, please go to "{{verification_uri}}/{{verification_code}}".
+To avoid bots, we need to verify that you are an actual human. To do so, please go to "{{verification_uri}}?verificationcode={{verification_code}}".
 
 If that does not work, please log in to GeneNetwork and copy the verification code below when requested: