Exemple #1
0
    def on_post(self, req, resp):
        if req.get_header("content-type") != "application/json":
            resp.status = "400 Bad Request"
            resp.content_type = "text"
            resp.body = "Data was not of type 'application/json'"
            return

        event_type = req.get_header("X-GitHub-Event")
        data = json.load(req.bounded_stream)

        state = data["state"]
        project = data["name"]
        context = data["context"]
        branches = [b["name"] for b in data["branches"]]

        if event_type != "status":
            return

        if not project.startswith("GlowstoneMC/"):
            return
        if not context.startswith("ci/circleci"):
            return
        if state != "success":
            return
        if "dev" not in branches and "master" not in branches:
            return

        celery.send_task(
            "download_javadocs",
            args=[project]
        )

        return
Exemple #2
0
    def on_post(self, req, resp):
        user = req.context["user"]
        db_session = req.context["db_session"]

        db_session.query(BackupCode).filter_by(user=user).delete(
            synchronize_session="fetch")

        backup_codes = []

        for i in range(10):
            token = secrets.token_urlsafe(24)
            db_session.add(BackupCode(user=user, code=token))
            backup_codes.append(token)

        celery.send_task("send_email",
                         args=["backup_codes", user.email, "MFA backup codes"],
                         kwargs={"codes": backup_codes})

        resp.append_header("Refresh", "5;url=/settings")

        return self.render_template(
            req,
            resp,
            "message_gate.html",
            gate_message=Message("success", "New codes generated",
                                 "New backup codes have been emailed to you."),
            redirect_uri="/settings")
Exemple #3
0
def send_nodebb(title, url, markdown, username, email, post_id):
    with send_nodebb.database.session() as session:
        settings = {}

        # Load up all NodeBB settings

        try:
            for setting in session.query(Setting).filter(
                    Setting.key.like("nodebb_%")).all():
                settings[setting.key] = setting.value
        except Exception as e:
            logging.getLogger("send_nodebb").error(
                "Failed to get NodeBB settings: {}".format(e))
            return
        finally:
            session.close()

        for key in NODEBB_NEEDED_KEYS:
            if key not in settings:
                return  # Not enough settings available

        nodebb_url = settings["nodebb_base_url"] + "{}"

        # Attempt to find a user object by email

        try:
            resp = requests.get(
                nodebb_url.format(NODEBB_READ_EMAIL.format(email)))
        except Exception as e:
            logging.getLogger("send_nodebb").warning(
                "Failed to find a user for {}: {}".format(email, e))
            uid = settings["nodebb_default_user_id"]
            title = "{} (by {})".format(title, username)
        else:
            data = resp.json()
            uid = data["uid"]

        markdown = "{}\n\n*This post was mirrored from [the site]({}).*".format(
            markdown, url)

        try:
            requests.post(nodebb_url.format(NODEBB_WRITE_POST),
                          data={
                              "_uid": uid,
                              "cid": settings["nodebb_category_id"],
                              "title": title,
                              "content": markdown
                          },
                          headers={
                              "Authorization":
                              "Bearer {}".format(settings["nodebb_api_key"])
                          })

            app.send_task("link_comments", args=[post_id])
        except Exception as e:
            logging.getLogger("send_nodebb").error(
                "Unable to create post: {}".format(e))
Exemple #4
0
    def on_get(self, req, resp):
        db_session = req.context["db_session"]
        params = {}

        if not req.get_param("product", store=params):
            raise HTTPNotFound()

        try:
            product = db_session.query(Product).filter_by(
                id=int(params["product"])).one()

        except NoResultFound:
            raise HTTPNotFound()
        else:
            celery.send_task("github_import",
                             args=[product.id, "GlowstoneMC", product.name],
                             kwargs={})

            raise HTTPTemporaryRedirect("/admin/products/")
Exemple #5
0
def notify_post(post: NewsPost):
    post_url = "https://glowstone.net/news/{}".format(post.id)

    # Discord

    md = post.summary

    md += "\n\n"
    md += "[Click here for more]({})".format(post_url)

    discord_embed = {
        "title": post.title,
        "description": md,
        "url": post_url,
        "author": {
            "name": post.user.username,
            "url": "https://glowstone.net/"
        }
    }

    app.send_task("send_discord", args=[discord_embed])

    # Twitter

    app.send_task("send_twitter", args=[post.title, post_url])

    # NodeBB

    app.send_task("send_nodebb",
                  args=[
                      post.title, post_url, post.markdown, post.user.username,
                      post.user.email, post.id
                  ])
Exemple #6
0
    def on_get(self, req, resp):
        params = {}
        resp.append_header("Refresh", "5;url=/admin/news/")

        if not req.get_param("post", store=params):
            return self.render_template(
                req,
                resp,
                "admin/message_gate.html",
                gate_message=Message(
                    "danger", "Missing post ID",
                    "Please include the ID of the post you want to relink"),
                redirect_uri="/admin/news")

        db_session = req.context["db_session"]

        try:
            post = db_session.query(NewsPost).filter_by(
                id=int(params["post"])).one()
        except NoResultFound:
            return self.render_template(req,
                                        resp,
                                        "admin/message_gate.html",
                                        gate_message=Message(
                                            "danger", "Error",
                                            "No such post: {}".format(
                                                params["post"])),
                                        redirect_uri="/admin/news")
        else:
            celery.send_task("link_comments", args=[post.id])

            return self.render_template(req,
                                        resp,
                                        "admin/message_gate.html",
                                        gate_message=Message(
                                            "success", "Relinking scheduled",
                                            "This post is being relinked."),
                                        redirect_uri="/admin/news")
Exemple #7
0
    def on_post(self, req, resp):
        user = req.context["user"]
        db_session = req.context["db_session"]

        db_session.query(BackupCode).filter_by(user=user).delete(
            synchronize_session="fetch")

        user.mfa_enabled = False
        user.mfa_token = None

        celery.send_task("send_email",
                         args=["mfa_disabled", user.email, "MFA disabled"],
                         kwargs={})

        resp.append_header("Refresh", "5;url=/settings")

        return self.render_template(req,
                                    resp,
                                    "message_gate.html",
                                    gate_message=Message(
                                        "success", "MFA disabled",
                                        "You have disabled MFA."),
                                    redirect_uri="/settings")
Exemple #8
0
    def step_two(self, req, resp):
        user = req.context["user"]
        totp = pyotp.TOTP(user.mfa_token)
        code = req.get_param("code")
        db_session = req.context["db_session"]

        if not code:
            uri = totp.provisioning_uri("{}@glowstone.net".format(
                user.username),
                                        issuer_name="Glowstone")

            image = qrcode.make(uri)
            buffer = BytesIO()

            image.save(buffer, format="PNG")
            qr_code = base64.b64encode(buffer.getvalue()).decode("UTF-8")

            return self.render_template(
                req,
                resp,
                "mfa/setup/step_two.html",
                message=Message(
                    "danger", "Missing code",
                    "Please enter a code from your authenticator application to continue."
                ),
                qr_code=qr_code)

        if totp.verify(code):
            backup_codes = []

            for i in range(10):
                token = secrets.token_urlsafe(24)
                db_session.add(BackupCode(user=user, code=token))
                backup_codes.append(token)

            celery.send_task(
                "send_email",
                args=["backup_codes", user.email, "MFA backup codes"],
                kwargs={"codes": backup_codes})

            user.mfa_enabled = True

            return self.render_template(req, resp, "mfa/setup/complete.html")
        else:
            uri = totp.provisioning_uri("{}@glowstone.net".format(
                user.username),
                                        issuer_name="Glowstone")

            image = qrcode.make(uri)
            buffer = BytesIO()

            image.save(buffer, format="PNG")
            qr_code = base64.b64encode(buffer.getvalue()).decode("UTF-8")

            return self.render_template(
                req,
                resp,
                "mfa/setup/step_two.html",
                message=Message(
                    "danger", "Invalid code",
                    "The auth code you provided was invalid - please try again."
                ),
                qr_code=qr_code)
Exemple #9
0
    def on_post(self, req, resp):
        if req.context["user"]:
            resp.append_header("Refresh", "5;url=/")
            return self.render_template(
                req, resp, "message_gate.html",
                gate_message=Message(
                    "danger", "Already logged in",
                    "You're already logged in!"
                ),
                redirect_uri="/"
            )

        params = {}

        if not req.get_param("g-recaptcha-response", store=params):
            return self.render_template(
                req, resp, "register.html",
                message=Message(
                    "danger", "Failed CAPTCHA",
                    "Unfortunately, we were not able to verify you by CAPTCHA. Please try again."
                ),
                csrf=resp.csrf
            )

        http = Session()
        captcha_response = http.post(
            RECAPTCHA_URL, data={
                "secret": self.manager.database.config.recaptcha_secret,
                "response": params["g-recaptcha-response"]
            }
        ).json()

        if not captcha_response["success"]:
            return self.render_template(
                req, resp, "register.html",
                message=Message(
                    "danger", "Failed CAPTCHA",
                    "Unfortunately, we were not able to verify you by CAPTCHA. Please try again."
                ),
                csrf=resp.csrf
            )

        if not req.get_param("username", store=params) \
                or not req.get_param("email", store=params) \
                or not req.get_param("password", store=params) \
                or not req.get_param("confirm_password", store=params):

            return self.render_template(
                req, resp, "register.html",
                message=Message("danger", "Missing input", "Please fill out the entire form"),
                csrf=resp.csrf
            )

        if not params["password"] == params["confirm_password"]:
            return self.render_template(
                req, resp, "register.html",
                message=Message("danger", "Passwords do not match", "Please ensure that your passwords match"),
                csrf=resp.csrf
            )

        db_session = req.context["db_session"]

        try:
            db_session.query(User).filter_by(username=params["username"]).one()
        except NoResultFound:
            pass
        else:
            return self.render_template(
                req, resp, "register.html",
                message=Message("danger", "User already exists", "That username is already taken - please try another"),
                csrf=resp.csrf
            )

        try:
            db_session.query(User).filter_by(email=params["email"]).one()
        except NoResultFound:
            pass
        else:
            return self.render_template(
                req, resp, "register.html",
                message=Message("danger", "Email already used", "An account already exists for that email address"),
                csrf=resp.csrf
            )

        password = base64.b64encode(hashlib.sha256(params["password"].encode("utf-8")).digest())
        hashed_password = bcrypt.hashpw(password, bcrypt.gensalt()).decode("utf-8")

        user = User(
            username=params["username"], password=hashed_password, created=datetime.datetime.now(),
            email=params["email"], email_verified=not self.db.config.email["use"],
            admin=(params["username"] == self.manager.database.config.admin_username)
        )

        db_session.add(user)

        resp.append_header("Refresh", "10;url=/")

        if self.db.config.email["use"]:
            key = secrets.token_urlsafe(32)
            email_code = EmailCode(
                user=user, code=key
            )

            db_session.add(email_code)

            celery.send_task(
                "send_email",
                args=["email_verification", user.email, "Email verification"],
                kwargs={"verify_url": "/login/verify/{}".format(key)}
            )

            return self.render_template(
                req, resp, "message_gate.html",
                gate_message=Message(
                    "info", "Registered", "Your account has been registered - please check your email to verify it!"
                ),
                redirect_uri="/"
            )

        return self.render_template(
            req, resp, "message_gate.html",
            gate_message=Message(
                "info", "Registered", "Your account has been registered successfully."
            ),
            redirect_uri="/"
        )
Exemple #10
0
    def on_post(self, req, resp):
        params = {}
        errors = []
        updated = []

        user = req.context["user"]
        user_email = user.email

        if not req.get_param("password", store=params):
            return self.render_template(
                req,
                resp,
                "users/settings.html",
                message=Message(
                    "danger", "Missing password",
                    "Please enter your current password to make changes."),
                user=user)

        params["password"] = base64.b64encode(
            hashlib.sha256(params["password"].encode("utf-8")).digest())

        db_session = req.context["db_session"]

        if not bcrypt.checkpw(params["password"],
                              user.password.encode("UTF-8")):
            return self.render_template(
                req,
                resp,
                "users/settings.html",
                message=Message("danger", "Incorrect password",
                                "The password you entered was incorrect."),
                user=user)

        if not errors:
            if req.get_param("new_password", store=params):
                if not req.get_param("new_password_again", store=params):
                    errors.append("Please confirm your new password.")
                elif not params["new_password"] == params["new_password_again"]:
                    errors.append("Your new passwords do not match.")
                else:
                    password = base64.b64encode(
                        hashlib.sha256(
                            params["new_password"].encode("utf-8")).digest())
                    hashed_password = bcrypt.hashpw(
                        password, bcrypt.gensalt()).decode("utf-8")

                    user.password = hashed_password
                    updated.append("Password")

        if not errors:
            if req.get_param("email", store=params) and params["email"]:
                key = secrets.token_urlsafe(32)
                email_code = EmailCode(user=user, code=key)

                db_session.add(email_code)

                celery.send_task(
                    "send_email",
                    args=[
                        "email_verification", user.email, "Email verification"
                    ],
                    kwargs={"verify_url": "/login/verify/{}".format(key)})

                user.email = params["email"]
                user.email_verified = False

                updated.append("Email")

        if errors:
            return self.render_template(
                req,
                resp,
                "users/settings.html",
                message=Message(
                    "danger", "Error",
                    "The following problems were found - nothing has been changed. <br /><ul>{}</ul>"
                    .format("".join("<li>{}</li>".format(error)
                                    for error in errors))),
                user=user)

        if updated:
            updated = ", ".join(updated)

            celery.send_task(
                "send_email",
                args=["settings_changed", user_email, "Settings Changed"],
                kwargs={"settings": updated})

            resp.append_header("Refresh", "10;url=/profile")

            return self.render_template(
                req,
                resp,
                "message_gate.html",
                gate_message=Message(
                    "info", "Updated",
                    "You have updated the following settings: {}<br />If you updated your email, "
                    "remember to verify it - or you won't be able to log in!".
                    format(updated)),
                redirect_uri="/profile")

        return self.render_template(req,
                                    resp,
                                    "users/settings.html",
                                    message=Message(
                                        "warning", "No changes",
                                        "You didn't change any settings."),
                                    user=user)