def dispatch_request(self) -> str: if ("email" not in flask.request.headers or "uid" not in flask.request.headers or "token" not in flask.request.headers): self.logger.info( "invalid request some information missing, aborting.") return flask.abort(400) # check if request is legit email = flask.request.headers["email"] token = flask.request.headers["token"] with sentry_sdk.configure_scope() as scope: scope.user = { "email": email, } if not register_tools.good_token(email, token): self.logger.info(f"bad token {token} used for email {email}") return flask.abort(403) # check db for username requested_username = flask.request.headers["uid"] if register_tools.is_in_ldap(requested_username): self.logger.info(f"username {requested_username} is in use") return "Not available" self.logger.info(f"username {requested_username} available") return "Available"
def dispatch_request(self) -> str: # make sure token is valid email = flask.request.form["email"] uri = flask.request.form["_token"] mysql_conn = None if not register_tools.good_token(email, uri): self.logger.warn(f"invalid token {uri} for email {email}") return flask.render_template( "index.html", page="login", error_message="Your token has expired or never existed. Please try again or contact us", ) # make sure form is flled out and username is still legit form_fields = ( flask.request.form["email"], flask.request.form["_token"], flask.request.form["uid"], flask.request.form["name"], ) if not all(form_fields): return flask.render_template( "form.html", email_address=email, token=uri, error_message="You must fill out all of the fields", ) user = flask.request.form["uid"] if user != user.lower(): return flask.render_template( "form.html", email_address=email, token=uri, error_message="The requested username contains uppercase characters.\ Please enter a username in lowercase", ) if len(user) > 15: return flask.render_template( "form.html", email_address=email, token=uri, error_message="The requested username is too long. Maximum length is 15 characters", ) try: if register_tools.is_in_ldap(user): self.logger.info(f"username {user} not available") return flask.render_template( "form.html", email_address=email, token=uri, error_message="The requested username is not available", ) # add user to ldap db info = register_tools.add_ldap_user(user) # add all info to Netsoc MySQL DB info["name"] = flask.request.form["name"] info["email"] = email mysql_conn = register_tools.add_netsoc_database(info) mysql_pass = mysql.create_user(user) # send user's details to them if not register_tools.send_details_email(email, user, info["password"], mysql_pass): self.logger.error(f"failed to send confirmation email") # initialise the user's home directories so they can use netsoc admin # without ever having to SSH into the server. if not config.FLASK_CONFIG["debug"]: register_tools.initialise_directories(user, info["password"]) # registration complete, remove their token register_tools.remove_token(email) # all went well, commit changes to MySQL mysql_conn.commit() except register_tools.UserExistsInLDAPException: return flask.render_template( "index.html", page="login", error_message="A user already exists with that username.", ) except (register_tools.LDAPException, register_tools.MySQLException) as e: self.logger.error(f"ldap or mysql error when creating user: {e}") # If an error occured, roll back changes register_tools.remove_token(email) if mysql_conn is not None: mysql_conn.rollback() if register_tools.is_in_ldap(user): register_tools.remove_ldap_user(user) mysql.delete_user(user) return flask.render_template( "index.html", page="login", error_message="An error occured. Please try again or contact us", ) except Exception as e: self.logger.error(f"error creating user: {e}") # If an error occured, roll back changes register_tools.remove_token(email) if mysql_conn is not None: mysql_conn.rollback() if register_tools.is_in_ldap(user): register_tools.remove_ldap_user(user) # TODO preserve stacktrace raise e finally: if mysql_conn is not None: mysql_conn.close() caption = "Thank you!" message = "An email has been sent with your log-in details. Please change your password as soon as you log in." self.logger.info(f"successfully signed up {flask.request.form['name']} and confirmation email sent") return flask.render_template("message.html", caption=caption, message=message)
def dispatch_request(self) -> str: # make sure token is valid email = flask.request.form["email"] token = flask.request.form["_token"] with sentry_sdk.configure_scope() as scope: scope.user = { "email": email, } mysql_conn = None if not register_tools.good_token(email, token): self.logger.warn("invalid token to signup for email", token=token, email=email) return flask.render_template( "index.html", page="login", error_message= "Your token has expired or never existed. Please try again or contact us", ) # make sure form is flled out and username is still legit form_fields = ( flask.request.form["email"], flask.request.form["_token"], flask.request.form["uid"], flask.request.form["name"], ) if not all(form_fields): return flask.render_template( "form.html", email_address=email, token=token, error_message="You must fill out all of the fields", ) user = flask.request.form["uid"] patternStart = re.compile("^[a-z0-9]") if not patternStart.match(user): return flask.render_template( "form.html", email_address=email, token=token, error_message= "Username must start with a lower case letter or a number only", ) patternEnd = re.compile(".+[a-z0-9]$") if not patternEnd.match(user): return flask.render_template( "form.html", email_address=email, token=token, error_message= "Username must end with a lower case letter or a number only", ) pattern = re.compile("^[a-z0-9]([a-z0-9\\-\\_]{0,60}[a-z0-9])$") if not pattern.match(user): return flask.render_template( "form.html", email_address=email, token=token, error_message= "Username must be all lower case letters, numbers, hyphens or underscores only", ) if len(user) > 15: return flask.render_template( "form.html", email_address=email, token=token, error_message= "The requested username is too long. Maximum length is 15 characters", ) try: if register_tools.is_in_ldap(user): self.logger.info( "user tried signing up with already taken username", username=user, email=email, token=token) return flask.render_template( "form.html", email_address=email, token=token, error_message="The requested username is not available", ) # add user to ldap db info = register_tools.add_ldap_user(user) # add all info to Netsoc MySQL DB info["name"] = flask.request.form["name"] info["email"] = email mysql_conn = register_tools.add_netsoc_database(info) mysql_pass = mysql.create_user(user) # send user's details to them if not register_tools.send_details_email( email, user, info["password"], mysql_pass): # We should really either throw exception in send_details_email or return something # more useful :( self.logger.error("failed to send confirmation email") # initialise the user's home directories so they can use netsoc admin # without ever having to SSH into the server. if not config.FLASK_CONFIG["debug"]: register_tools.initialise_directories(user, info["password"]) # all went well, commit changes to MySQL mysql_conn.commit() # registration complete, remove their token register_tools.remove_token(email) except register_tools.UserExistsInLDAPException: return flask.render_template( "index.html", page="login", error_message="A user already exists with that username.", ) except (register_tools.LDAPException, register_tools.MySQLException) as e: self.logger.error(f"ldap or mysql error when creating user: {e}") # If an error occured, roll back changes register_tools.remove_token(email) if mysql_conn is not None: mysql_conn.rollback() if register_tools.is_in_ldap(user): register_tools.remove_ldap_user(user) mysql.delete_user(user) return flask.render_template( "index.html", page="login", error_message= "An error occured. Please try again or contact us", ) except Exception as e: # If an error occured, roll back changes register_tools.remove_token(email) if mysql_conn is not None: mysql_conn.rollback() if register_tools.is_in_ldap(user): register_tools.remove_ldap_user(user) # TODO preserve stacktrace raise e finally: if mysql_conn is not None: mysql_conn.close() caption = "Thank you!" message = "An email has been sent with your log-in details. Please change your password as soon as you log in." self.logger.info( f"successfully signed up {flask.request.form['name']} and confirmation email sent" ) return flask.render_template("message.html", caption=caption, message=message)