Exemplo n.º 1
0
    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"
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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)