Пример #1
0
    def do_task(self):
        super().do_task()

        cur = db.cursor()
        result = cur.execute(
            read_query_file(
                "select-user-name-waiting-to-be-approved.sql")).fetchall()
        if result:
            self.log_task()
            names = []
            (result, col_names) = rowify(result, cur.description)
            for item in result:
                names.append("{approved_date} - {display_name}".format(**item))

            message = "\n".join(names)

            # Send a notification email (silent fail if not configured)
            current_app.logger.debug(message)
            if not current_app.config.get("DEBUG", True):
                try:
                    send_message(
                        current_app.config.get("EMAIL_MODERATOR"),
                        "Puzzle Massive - new names",
                        message,
                        current_app.config,
                    )
                except Exception as err:
                    current_app.logger.warning(
                        "Failed to send notification message. {}".format(err))
                    pass

        cur.close()
    def post(self):
        ""
        response = {"message": "", "name": "error"}

        is_shareduser = False
        user = current_app.secure_cookie.get(u"user")
        if not user:
            user = user_id_from_ip(request.headers.get("X-Real-IP"))
            is_shareduser = True

        if user == None:
            response["message"] = "User not signed in."
            response["name"] = "error"
            return make_response(json.jsonify(response), 400)

        user = int(user)

        args = {}
        if request.form:
            args.update(request.form.to_dict(flat=True))

        email = args.get("email", "").strip().lower()
        if len(email) > EMAIL_MAXLENGTH:
            response["message"] = "E-mail is too long."
            response["name"] = "error"
            return make_response(json.jsonify(response), 400)

        cur = db.cursor()

        result = cur.execute(fetch_query_string("user-has-player-account.sql"),
                             {
                                 "player_id": user
                             }).fetchone()
        if not result or result[0] == 0:
            cur.execute(
                fetch_query_string("init-player-account-for-user.sql"),
                {"player_id": user},
            )

        result = cur.execute(
            fetch_query_string("select-player-details-for-player-id.sql"),
            {
                "player_id": user
            },
        ).fetchall()
        if not result:
            # This shouldn't happen if user-has-player-account.sql
            response["message"] = "No player account."
            response["name"] = "error"
            cur.close()
            db.commit()
            return make_response(json.jsonify(response), 400)
        (result, col_names) = rowify(result, cur.description)
        existing_player_data = result[0]

        # Prevent shareduser changing the verified email address.
        if is_shareduser and existing_player_data["is_verifying_email"]:
            response[
                "message"] = "A player on this same network has already submitted an email address. Changing it is not allowed until the account has been claimed or the verify email token expires."
            response["name"] = "error"
            return make_response(json.jsonify(response), 400)

        if existing_player_data["email"] == email:
            response[
                "message"] = "No changes made to e-mail address ({}).  The e-mail address is stored as lowercase.".format(
                    email)
            response["name"] = "error"
        else:
            if email == "":
                cur.execute(
                    fetch_query_string("remove-player-account-email.sql"),
                    {"player_id": user},
                )
                response["message"] = "Removed e-mail from player account."
                response["name"] = "success"
            else:
                # Verify that email is unique
                result = cur.execute(
                    fetch_query_string(
                        "select-player-by-verified-email-address.sql"),
                    {
                        "email": email
                    },
                ).fetchall()
                if result:
                    response[
                        "message"] = "A player has already registered this e-mail address."
                    response["name"] = "error"
                    cur.close()
                    db.commit()
                    return make_response(json.jsonify(response), 400)

                if existing_player_data["is_verifying_email"]:
                    response[
                        "message"] = "An e-mail address is already in the process of verification for this player.  Please wait."
                    response["name"] = "error"
                    cur.close()
                    db.commit()
                    return make_response(json.jsonify(response), 400)

                cur.execute(
                    fetch_query_string("update-player-account-email.sql"),
                    {
                        "player_id": user,
                        "email": email
                    },
                )
                cur.execute(
                    fetch_query_string(
                        "update-player-account-email-verified.sql"),
                    {
                        "player_id": user,
                        "email_verified": 0,
                    },
                )

                # Send verification email (silent fail if not configured)
                token = uuid.uuid4().hex
                message = """
Please verify your e-mail address with Puzzle Massive by following the link below.

http://{DOMAIN_NAME}/chill/site/claim-player/{token}/

Complete registering your e-mail address by visiting that web page and clicking
the "verify player" button.

You can ignore this message if you didn't initiate the request.
                """.format(token=token,
                           DOMAIN_NAME=current_app.config.get("DOMAIN_NAME"))
                current_app.logger.debug(message)
                if not current_app.config.get("DEBUG", True):
                    try:
                        send_message(
                            email,
                            "Puzzle Massive - verify e-mail address",
                            message,
                            current_app.config,
                        )
                    except Exception as err:
                        current_app.logger.warning(
                            "Failed to send verification message. email: {email}\n {message}\n error: {err}"
                            .format(err=err, email=email, message=message))
                        pass

                cur.execute(
                    fetch_query_string(
                        "update-player-account-email-verify-token.sql"),
                    {
                        "player_id": user,
                        "email_verify_token": token,
                        "expire_token_timeout": "+1 hour",
                    },
                )

                response[
                    "message"] = "Updated e-mail ({}) for player account.  ".format(
                        email)
                response["name"] = "success"

        db.commit()
        cur.close()
        return make_response(json.jsonify(response), 202)
Пример #3
0
    def post(self):
        args = {}
        if request.form:
            args.update(request.form.to_dict(flat=True))
            args["features"] = set(request.form.getlist("features"))

        # Check pieces arg
        try:
            pieces = int(
                args.get("pieces", current_app.config["MINIMUM_PIECE_COUNT"]))
        except ValueError as err:
            abort(400)
        if (not current_app.config["MINIMUM_PIECE_COUNT"] <= pieces <=
                current_app.config["MAXIMUM_PIECE_COUNT"]):
            abort(400)

        bg_color = check_bg_color(args.get("bg_color", "#808080")[:50])

        user = int(
            current_app.secure_cookie.get(u"user")
            or user_id_from_ip(request.headers.get("X-Real-IP")))

        permission = int(args.get("permission", PUBLIC))
        if permission not in (PUBLIC, PRIVATE):
            permission = PUBLIC

        description = escape(args.get("description", "").strip())[:1000]

        # Check secret_message
        secret_message = escape(args.get("secret_message", ""))[:1000]

        # Check link and validate
        link = url_fix(args.get("link", "").strip())[:100]

        if not link and not description:
            abort(400)

        puzzle_id = uuid.uuid1().hex

        features = set(args.get("features", []))

        cur = db.cursor()
        d = {
            "puzzle_id": puzzle_id,
            "pieces": pieces,
            "link": link,
            "description": description,
            "bg_color": bg_color,
            "owner": user,
            "status": SUGGESTED,
            "permission": permission,
        }
        cur.execute(
            """insert into Puzzle (
        puzzle_id,
        pieces,
        link,
        description,
        bg_color,
        owner,
        status,
        permission) values
        (:puzzle_id,
        :pieces,
        :link,
        :description,
        :bg_color,
        :owner,
        :status,
        :permission);
        """,
            d,
        )
        db.commit()

        puzzle = rowify(
            cur.execute(
                fetch_query_string("select_puzzle_id_by_puzzle_id.sql"),
                {
                    "puzzle_id": puzzle_id
                },
            ).fetchall(),
            cur.description,
        )[0][0]
        puzzle = puzzle["puzzle"]

        result = cur.execute(
            fetch_query_string("select-puzzle-features-enabled.sql"), {
                "enabled": 1
            }).fetchall()
        if result:
            (puzzle_features, _) = rowify(result, cur.description)
            # Add puzzle features
            for puzzle_feature in puzzle_features:
                if (puzzle_feature["slug"] == "hidden-preview"
                        and "hidden-preview" in features):
                    cur.execute(
                        fetch_query_string(
                            "add-puzzle-feature-to-puzzle-by-id--hidden-preview.sql"
                        ),
                        {
                            "puzzle": puzzle,
                            "puzzle_feature": puzzle_feature["id"]
                        },
                    )
                elif (puzzle_feature["slug"] == "secret-message"
                      and "secret-message" in features):
                    cur.execute(
                        fetch_query_string(
                            "add-puzzle-feature-to-puzzle-by-id--secret-message.sql"
                        ),
                        {
                            "puzzle": puzzle,
                            "puzzle_feature": puzzle_feature["id"],
                            "message": secret_message,
                        },
                    )

        db.commit()
        cur.close()

        # Send a notification email (silent fail if not configured)
        message = """
http://{DOMAIN_NAME}/chill/site/admin/puzzle/suggested/{puzzle_id}/

pieces: {pieces}
bg_color: {bg_color}
owner: {owner}

link: {link}
description: {description}
        """.format(DOMAIN_NAME=current_app.config.get("DOMAIN_NAME"), **d)
        current_app.logger.debug(message)
        if not current_app.config.get("DEBUG", True):
            try:
                send_message(
                    current_app.config.get("EMAIL_MODERATOR"),
                    "Suggested Image",
                    message,
                    current_app.config,
                )
            except Exception as err:
                current_app.logger.warning(
                    "Failed to send notification message for suggested image. email: {email}\n {message}\n error: {err}"
                    .format(
                        err=err,
                        email=current_app.config.get("EMAIL_MODERATOR"),
                        message=message,
                    ))
                pass

        # Redirect to a thank you page (not revealing the puzzle_id)
        return redirect("/chill/site/suggested-puzzle-thank-you/", code=303)
    def post(self):
        ""
        response = {"message": "", "name": "error"}

        user = current_app.secure_cookie.get(u"user")
        if user:
            response[
                "message"] = "User currently logged in.  No need to reset the login by e-mail."
            response["name"] = "error"
            return make_response(json.jsonify(response), 400)

        user = user_id_from_ip(request.headers.get("X-Real-IP"))
        if user == None:
            response["message"] = "Shared user not currently logged in."
            response["name"] = "error"
            return make_response(json.jsonify(response), 400)

        args = {}
        if request.form:
            args.update(request.form.to_dict(flat=True))

        email = args.get("email", "").strip().lower()
        if len(email) > EMAIL_MAXLENGTH:
            response["message"] = "E-mail is too long."
            response["name"] = "error"
            return make_response(json.jsonify(response), 400)

        cur = db.cursor()

        # Get user by their verified email address
        result = cur.execute(
            fetch_query_string("get-user-by-verified-email-address.sql"),
            {
                "email": email
            },
        ).fetchone()
        if not result or result[0] == 0:
            response[
                "message"] = "Sorry, that e-mail address has not been verified."
            response["name"] = "error"
            cur.close()
            db.commit()
            return make_response(json.jsonify(response), 400)
        else:
            user = result[0]

        result = cur.execute(
            fetch_query_string("select-player-details-for-player-id.sql"),
            {
                "player_id": user
            },
        ).fetchall()
        if not result:
            # This shouldn't happen if user-has-player-account.sql
            response["message"] = "No player account."
            response["name"] = "error"
            cur.close()
            db.commit()
            return make_response(json.jsonify(response), 400)
        (result, col_names) = rowify(result, cur.description)
        existing_player_data = result[0]

        if existing_player_data["has_active_reset_login_token"]:
            response[
                "message"] = "Please check your e-mail for a reset login link.  The reset login link that was sent earlier has not expired."
            response["name"] = "error"
            cur.close()
            db.commit()
            return make_response(json.jsonify(response), 400)

        # Send a link to reset the login (silent fail if not configured)
        token = uuid.uuid4().hex
        message = """
The link below is only valid for a short time.  Use it to reset your login link
for Puzzle Massive.

http://{DOMAIN_NAME}/chill/site/reset-login/{token}/

After visiting that web page and clicking the reset login button; a new login
link will be created. Any older ones will no longer be valid.

You can ignore this message if you didn't initiate the request.
        """.format(token=token,
                   DOMAIN_NAME=current_app.config.get("DOMAIN_NAME"))
        current_app.logger.debug(message)
        email_sent = False
        if not current_app.config.get("DEBUG", True):
            try:
                send_message(email, "Puzzle Massive - reset login", message,
                             current_app.config)
                email_sent = True
            except Exception as err:
                current_app.logger.warning(
                    "Failed to send reset login message. email: {email}\n {message}\n error: {err}"
                    .format(err=err, email=email, message=message))
                email_sent = False

        cur.execute(
            fetch_query_string("update-player-account-login-token.sql"),
            {
                "player_id": user,
                "reset_login_token": token,
                "expire_token_timeout": "+1 day",
            },
        )

        if current_app.config.get("DEBUG", True):
            response[
                "message"] = "A reset login link has been sent to your e-mail. DEBUG is True, so did not really send the email. Check the logs for the login link."
            response["name"] = "success"
        elif not email_sent:
            response[
                "message"] = "Failed to send reset login link to your e-mail.".format(
                    email)
            response["name"] = "error"
        else:
            response[
                "message"] = "A reset login link has been sent to your e-mail.".format(
                    email)
            response["name"] = "success"

        db.commit()
        cur.close()
        return make_response(json.jsonify(response), 202)