From ffe9e7104ba83b73d78d66de2d29ad4ace6de2da Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Thu, 30 May 2024 16:13:04 -0500 Subject: Provide endpoint for verification and do verification --- gn_auth/auth/authorisation/users/views.py | 54 ++++++++++++++++++++++++++++-- gn_auth/auth/errors.py | 3 ++ gn_auth/templates/emails/verify-email.html | 27 +++------------ gn_auth/templates/emails/verify-email.txt | 2 +- 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 @@ {{subject}} -

Thank you for registering an account with GeneNetwork.

@@ -28,8 +9,8 @@

To avoid bots, we need to verify that you are an actual human. To do so, please - + Click here .

@@ -38,10 +19,10 @@ If that does not work, please log in to GeneNetwork and copy the verification code below when requested:

- {{verification_code}} + {{verification_code}}

-

+

Please note that the verification code will expire in {{expiration_minutes}} minutes after it was generated.

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: -- cgit v1.2.3