diff options
-rw-r--r-- | gn_auth/auth/authentication/oauth2/views.py | 5 | ||||
-rw-r--r-- | gn_auth/auth/authorisation/users/views.py | 34 | ||||
-rw-r--r-- | gn_auth/templates/users/unverified-user.html | 69 |
3 files changed, 107 insertions, 1 deletions
diff --git a/gn_auth/auth/authentication/oauth2/views.py b/gn_auth/auth/authentication/oauth2/views.py index 7600ada..cf815ea 100644 --- a/gn_auth/auth/authentication/oauth2/views.py +++ b/gn_auth/auth/authentication/oauth2/views.py @@ -53,7 +53,7 @@ def authorise(): redirect_uri=request.args["redirect_uri"]) form = request.form - def __authorise__(conn: db.DbConnection) -> Response: + def __authorise__(conn: db.DbConnection): email_passwd_msg = "Email or password is invalid!" redirect_response = redirect(url_for("oauth2.auth.authorise", response_type=form["response_type"], @@ -64,6 +64,9 @@ def authorise(): form.get("user:email"), check_deliverability=False) user = user_by_email(conn, email["email"]) if valid_login(conn, user, form.get("user:password", "")): + if not user.verified: + return redirect(url_for( + "oauth2.users.handle_unverified"), code=307) return server.create_authorization_response(request=request, grant_user=user) flash(email_passwd_msg, "alert-danger") return redirect_response # type: ignore[return-value] diff --git a/gn_auth/auth/authorisation/users/views.py b/gn_auth/auth/authorisation/users/views.py index 638f0df..cb6775f 100644 --- a/gn_auth/auth/authorisation/users/views.py +++ b/gn_auth/auth/authorisation/users/views.py @@ -35,6 +35,7 @@ from gn_auth.auth.errors import ( UserVerificationError, UserRegistrationError) +from gn_auth.auth.authentication.users import valid_login, user_by_email 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 ( @@ -275,3 +276,36 @@ def list_all_users() -> Response: with require_oauth.acquire("profile group") as _the_token: return jsonify(tuple( asdict(user) for user in with_db_connection(list_users))) + +@users.route("/handle-unverified", methods=["POST"]) +def handle_unverified(): + """Handle case where user tries to login but is unverified""" + form = request.form + # TODO: Maybe have a GN2_URI setting here? + # or pass the client_id here? + return render_template( + "users/unverified-user.html", email=form.get("user:email")) + +@users.route("/send-verification", methods=["POST"]) +def send_verification_code(): + """Send verification code email.""" + form = request.form + with (db.connection(current_app.config["AUTH_DB"]) as conn, + db.cursor(conn) as cursor): + user = user_by_email(conn, form["user_email"]) + if valid_login(conn, user, form.get("user_password", "")): + cursor.execute( + "DELETE FROM user_verification_codes WHERE user_id=:user_id", + {"user_id": str(user.user_id)}) + send_verification_email(conn, user) + return jsonify({ + "status": "success", + "message": "Sent a verification code to your email." + }) + + resp = jsonify({ + "error": "InvalidLogin", + "error-description": "Invalid email or password." + }) + resp.code = 400 + return resp diff --git a/gn_auth/templates/users/unverified-user.html b/gn_auth/templates/users/unverified-user.html new file mode 100644 index 0000000..b2c6992 --- /dev/null +++ b/gn_auth/templates/users/unverified-user.html @@ -0,0 +1,69 @@ +{%extends "base.html"%} + +{%block title%}gn-auth: Verify Email{%endblock%} + +{%block pagetitle%}Verify Email{%endblock%} + +{%block content%} +{{flash_messages()}} + +<h1>Verify Your E-Mail</h1> + +<form id="frm-email-verification" method="POST" + action="{{url_for('oauth2.users.verify_user')}}"> + <legend>Email Verification</legend> + + <p>In order to reduce the number of bots we have to deal with, we no longer + allow sign-in with users who have not verified their accounts.</p> + + <p>We know this is annoying — especially if you already have an account, + and have been using it just fine — however, we have found that without + this check in place, we will get overrun by silly bots, which will ruin + every user's experience.</p> + + <p> + Do bear with us, enter the verification code you received via email below: + </p> + + <input type="hidden" name="email" value="email" /> + + <fieldset class="form-group"> + <label for="txt-verification-code" class="form-label"> + Verification Code</label> + <input id="txt-verification-code" name="verificationcode" type="text" + required="required" class="form-control" + placeholder="Enter your verification code here." /> + </fieldset> + + <fieldset> + <input type="submit" value="Verify Email Address" class="btn btn-primary" /> + </fieldset> +</form> + +<h2>Send Verification Code</h2> + +<form id="frm-send-verification-code" method="POST" + action="{{url_for('oauth2.users.send_verification_code')}}"> + <legend>Send Verification Code</legend> + + <p>If you have not received a verification code, or your code is already + expired, provide <strong>your GeneNetwork</strong> password and + click the "<em>Send Verification Code</em>" button below and we will send + you a new verification code.</p> + + <input type="hidden" name="user_email" value="{{email}}" /> + + <fieldset class="form-group"> + <label class="form-label">Email</label> + <label class="form-control">{{email}}</label> + </fieldset> + + <fieldset class="form-group"> + <label for="txt-password" class="form-label">Password</label> + <input id="txt-password" name="user_password" type="password" + placeholder="Enter your GeneNetwork password" + class="form-control" /> + </fieldset> + <input type="submit" value="Send Verification Code" class="btn btn-danger" /> +</form> +{%endblock%} |