Ejemplo n.º 1
0
    def test_pieces_are_updated_after_reset(self):
        "The puzzle piece positions should be randomly placed after reset"
        with self.app.app_context():
            with self.app.test_client() as c:
                cur = self.db.cursor()
                result = cur.execute(
                    "select * from Piece where puzzle = :puzzle order by id",
                    {
                        "puzzle": self.puzzle
                    },
                ).fetchall()
                (before_positions, cols) = rowify(result, cur.description)
                pr.reset_puzzle_pieces(self.puzzle)
                result = cur.execute(
                    "select * from Piece where puzzle = :puzzle order by id",
                    {
                        "puzzle": self.puzzle
                    },
                ).fetchall()
                (after_positions, cols) = rowify(result, cur.description)

                has_changed = False
                for (index, before_piece) in enumerate(before_positions):
                    after_piece = after_positions[index]
                    if (before_piece["x"] != after_piece["x"]
                            or before_piece["y"] != after_piece["y"]):
                        has_changed = True
                        break

                self.assertTrue(has_changed, msg="piece positions change")
                cur.close()
Ejemplo n.º 2
0
def migrate_next_puzzle(puzzle):
    cur = db.cursor()
    logging.info("migrating puzzle {}".format(puzzle))

    # Update any original that have an empty url
    cur.execute(query_update_puzzle_file_original_null_url, {'puzzle': puzzle})

    # Update any original that have a '0' for url
    cur.execute(query_update_puzzle_file_original_s3_url, {'puzzle': puzzle})

    db.commit()

    result = cur.execute(query_select_puzzle_file_to_migrate_from_s3, {
        'puzzle': puzzle
    }).fetchall()
    if result:
        (result, col_names) = rowify(result, cur.description)
        for item in result:
            migrate_s3_puzzle(item)

    result = cur.execute(query_select_puzzle_file_to_migrate_from_unsplash, {
        'puzzle': puzzle,
    }).fetchall()
    if result:
        (result, col_names) = rowify(result, cur.description)
        for item in result:
            migrate_unsplash_puzzle(item)

    cur.close()
Ejemplo n.º 3
0
def user_id_from_ip(ip, skip_generate=True):
    cur = db.cursor()

    shareduser = current_app.secure_cookie.get(u"shareduser")
    if shareduser != None:
        # Check if this shareduser is still valid and another user hasn't chosen
        # a bit icon.
        result = cur.execute(
            fetch_query_string("select-user-by-id-and-no-password.sql"),
            {
                "id": shareduser
            },
        ).fetchall()
        if result:
            cur.close()
            return int(shareduser)

    # Handle players that had a cookie in their browser, but then deleted it.
    # Or new players that are from the same ip that existing players are on.
    # These players are shown the new-player page.
    result = cur.execute(
        fetch_query_string("select-user-id-by-ip-and-no-password.sql"), {
            "ip": ip
        }).fetchall()
    user_id = ANONYMOUS_USER_ID

    # No ip in db so create it except if the skip_generate flag is set
    if not result:
        if skip_generate:
            cur.close()
            return None
        login = generate_user_login()
        cur.execute(
            fetch_query_string("add-new-user-for-ip.sql"),
            {
                "ip": ip,
                "login": login,
                "points": current_app.config["NEW_USER_STARTING_POINTS"],
            },
        )
        db.commit()

        result = cur.execute(
            fetch_query_string("select-user-id-by-ip-and-login.sql"),
            {
                "ip": ip,
                "login": login
            },
        ).fetchall()
        (result, col_names) = rowify(result, cur.description)
        user_id = result[0]["id"]
    else:
        (result, col_names) = rowify(result, cur.description)
        user_id = result[0]["id"]

    cur.close()
    return user_id
Ejemplo n.º 4
0
def delete_puzzle_file(puzzle_id, file_name):
    ""

    cur = db.cursor()
    result = cur.execute(
        fetch_query_string("select-internal-puzzle-details-for-puzzle_id.sql"),
        {
            "puzzle_id": puzzle_id
        },
    ).fetchall()
    if not result:
        err_msg = {"msg": "No puzzle found", "status_code": 400}
        cur.close()
        return err_msg

    (result, col_names) = rowify(result, cur.description)
    puzzle_data = result[0]
    puzzle = puzzle_data["id"]

    result = cur.execute(
        fetch_query_string("select_puzzle_file_with_attribution.sql"),
        {
            "puzzle": puzzle,
            "name": file_name
        },
    ).fetchall()
    if result:
        (result, col_names) = rowify(result, cur.description)
        puzzle_file_with_attribution_data = result[0]

        # Delete previous attribution if it exists
        if puzzle_file_with_attribution_data["attribution_id"]:
            result = cur.execute(
                fetch_query_string("delete_attribution_from_puzzle_file.sql"),
                {"id": puzzle_file_with_attribution_data["puzzle_file_id"]},
            )
            result = cur.execute(
                fetch_query_string("delete_attribution.sql"),
                {
                    "attribution":
                    puzzle_file_with_attribution_data["attribution_id"]
                },
            )

    result = cur.execute(
        fetch_query_string("delete_puzzle_file_with_name_for_puzzle.sql"),
        {
            "puzzle": puzzle,
            "name": file_name
        },
    )
    db.commit()
    cur.close()

    msg = {"rowcount": result.rowcount, "msg": "Deleted", "status_code": 200}
    return msg
Ejemplo n.º 5
0
    def test_move_piece_to_join_immovable(self):
        "Move a piece to join immovable group"
        cur = self.db.cursor()

        (results, col_names) = rowify(cur.execute(self.query_puzzle_255),
                                      cur.description)
        testPuzzle = results[0]
        r = 0

        # Move 6 to join piece 4 which is immovable
        (piece, x, y) = (6, 446, 222)
        (topic, msg) = translate(0,
                                 testPuzzle,
                                 piece,
                                 x,
                                 y,
                                 r,
                                 db_file=self.tmp_db.name)

        expectedMsg = ":{piece}:{x}:{y}:0::\n:6:428:218:0:4:1\n:4::::4:".format(
            **locals())
        print("({0})".format(expectedMsg))
        print("[{0}]".format(msg))
        assert len(expectedMsg) == len(msg)
        for l in expectedMsg.split("\n"):
            assert l in msg
Ejemplo n.º 6
0
    def post(self, puzzle_id):
        "Ping and record the time in milliseconds for this player."
        now_ms = int(time.time() * 1000)
        response = {"message": "", "name": ""}

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

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

        user = int(user)

        cur = db.cursor()

        # Validate the puzzle_id
        result = cur.execute(
            fetch_query_string("select_viewable_puzzle_id.sql"),
            {
                "puzzle_id": puzzle_id
            },
        ).fetchall()
        if not result:
            response["message"] = "Invalid puzzle id."
            response["name"] = "error"
            cur.close()
            db.commit()
            return make_response(json.jsonify(response), 400)
        else:
            (result, col_names) = rowify(result, cur.description)
            puzzle = result[0].get("puzzle")
            status = result[0].get("status")
            if status != ACTIVE:
                response["message"] = "Puzzle not active"
                response["name"] = "invalid"
                cur.close()
                db.commit()
                return make_response(json.jsonify(response), 200)

        # publish to the puzzle channel the ping with the user id.  This will
        # allow that player to determine their latency.
        token = uuid.uuid4().hex[:4]
        pingtoken_key = get_pingtoken_key(puzzle, user, token)
        redis_connection.setex(pingtoken_key, 60, now_ms)

        current_app.logger.debug(
            "publish ping {puzzle_id}".format(puzzle_id=puzzle_id))
        sse.publish(
            "{user}:{token}".format(user=user, token=token),
            type="ping",
            channel="puzzle:{puzzle_id}".format(puzzle_id=puzzle_id),
        )
        response["message"] = "ping accepted"
        response["name"] = "accepted"
        response = make_response(json.jsonify(response), 202)
        cur.close()
        db.commit()
        return response
Ejemplo n.º 7
0
def delete_puzzle_timeline(puzzle_id):
    ""
    cur = db.cursor()
    result = cur.execute(
        fetch_query_string("select-internal-puzzle-details-for-puzzle_id.sql"),
        {
            "puzzle_id": puzzle_id
        },
    ).fetchall()
    if not result:
        err_msg = {"msg": "No puzzle found", "status_code": 400}
        cur.close()
        return err_msg

    (result, col_names) = rowify(result, cur.description)
    puzzle_data = result[0]
    puzzle = puzzle_data["id"]

    result = cur.execute(fetch_query_string("delete_puzzle_timeline.sql"),
                         {"puzzle": puzzle})
    cur.close()
    db.commit()

    redis_connection.delete("timeline:{puzzle}".format(puzzle=puzzle))
    redis_connection.delete("score:{puzzle}".format(puzzle=puzzle))

    msg = {"rowcount": result.rowcount, "msg": "Deleted", "status_code": 200}
    return msg
Ejemplo n.º 8
0
    def get(self):

        url_match = request.args.get("url_match", "/resources/%")

        cur = db.cursor()

        result = cur.execute(
            fetch_query_string(
                "select_rendered_puzzle_files_with_url_like.sql"),
            {
                "url_match": url_match
            },
        ).fetchall()
        if not result:
            puzzle_files = []
        else:
            (result, col_names) = rowify(result, cur.description)
            puzzle_files = result

        response = {
            "puzzle_files": puzzle_files,
        }

        cur.close()

        return make_response(json.jsonify(response), 200)
Ejemplo n.º 9
0
    def setUp(self):
        self.query_puzzle_255 = "select id as puzzle, table_width, table_height, mask_width, puzzle_id, pieces from Puzzle where id = 255"
        self.tmp_db = tempfile.NamedTemporaryFile(delete=False)
        self.db = sqlite3.connect(self.tmp_db.name)
        cur = self.db.cursor()

        for file_path in (
                "../queries/create_table_puzzle.sql",
                "../queries/create_table_piece.sql",
                "../queries/create_table_user.sql",
                "../queries/create_table_timeline.sql",
                "examplePuzzle.sql",
                "examplePiece.sql",
        ):
            with open(
                    os.path.normpath(
                        os.path.join(os.path.dirname(__file__), file_path)),
                    "r",
            ) as f:
                for statement in f.read().split(";"):
                    # print statement
                    cur.execute(statement)
                    self.db.commit()

        (results,
         col_names) = rowify(cur.execute("select id as puzzle from Puzzle"),
                             cur.description)

        for result in results:
            self.puzzles.append(result["puzzle"])
            convert(result["puzzle"], db_file=self.tmp_db.name)

        cur.close()
Ejemplo n.º 10
0
    def get(self, puzzle_id):
        ""
        cur = db.cursor()
        result = cur.execute(
            fetch_query_string("select_viewable_puzzle_id.sql"),
            {
                "puzzle_id": puzzle_id
            },
        ).fetchall()
        if not result:
            # 404 if puzzle does not exist
            abort(404)

        (result, col_names) = rowify(result, cur.description)
        puzzle = result[0].get("puzzle")
        status = result[0].get("status")
        now = int(time.time())

        count = (redis_connection.zcount(
            "timeline:{puzzle}".format(puzzle=puzzle), now - 5 * 60, "+inf")
                 or 0)

        player_active_count = {"now": now, "count": count}

        cur.close()
        return make_response(json.jsonify(player_active_count), 200)
Ejemplo n.º 11
0
    def get(self, puzzle_id):
        ""
        ip = request.headers.get("X-Real-IP")
        user = int(
            current_app.secure_cookie.get(u"user") or user_id_from_ip(ip))
        cur = db.cursor()
        result = cur.execute(
            fetch_query_string("select_viewable_puzzle_id.sql"),
            {
                "puzzle_id": puzzle_id
            },
        ).fetchall()
        if not result:
            # 404 if puzzle does not exist
            abort(404)

        (result, col_names) = rowify(result, cur.description)
        puzzle = result[0].get("puzzle")
        status = result[0].get("status")
        now = int(time.time())

        count = (redis_connection.zcount(
            "timeline:{puzzle}".format(puzzle=puzzle), now - 5 * 60, "+inf")
                 or 0)

        player_active_count = {"now": now, "count": count}

        cur.close()
        return json.jsonify(player_active_count)
Ejemplo n.º 12
0
    def test_join_two_pieces_not_in_group(self):
        "Join two pieces that are not grouped"
        cur = self.db.cursor()

        (results, col_names) = rowify(cur.execute(self.query_puzzle_255),
                                      cur.description)
        testPuzzle = results[0]
        r = 0

        (piece, x, y) = (6, 54, 61)
        (topic, msg) = translate(0,
                                 testPuzzle,
                                 piece,
                                 x,
                                 y,
                                 r,
                                 db_file=self.tmp_db.name)
        (piece, x, y) = (5, 130, 77)
        (topic, msg) = translate(0,
                                 testPuzzle,
                                 piece,
                                 x,
                                 y,
                                 r,
                                 db_file=self.tmp_db.name)
        # Piece 5 gets shifted to join piece 6, piece group 6 is created and both pieces join
        expectedMsg = ":{piece}:{x}:{y}:0::\n:5:119:61:0:6:\n:6::::6:".format(
            **locals())
        assert len(expectedMsg) == len(msg)
        for l in expectedMsg.split("\n"):
            assert l in msg
Ejemplo n.º 13
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()
Ejemplo n.º 14
0
    def test_move_grouped_piece_to_join_immovable(self):
        "Move a grouped piece to join immovable group"
        cur = self.db.cursor()

        (results, col_names) = rowify(cur.execute(self.query_puzzle_255),
                                      cur.description)
        testPuzzle = results[0]
        r = 0

        # Move 8 to join piece 4 which is immovable
        # (8,1,11) -> 4
        (piece, x, y) = (8, 367, 296)
        (topic, msg) = translate(0,
                                 testPuzzle,
                                 piece,
                                 x,
                                 y,
                                 r,
                                 db_file=self.tmp_db.name)

        expectedMsg = ":{piece}:{x}:{y}:90:8:\n:1:493:283::4:1\n:11:428:283::4:1\n:8::::4:\n:8:363:283:90:4:1".format(
            **locals())
        assert len(expectedMsg) == len(msg)
        for l in expectedMsg.split("\n"):
            assert l in msg
Ejemplo n.º 15
0
    def test_join_two_grouped_pieces_to_a_piece_not_grouped(self):
        "Join two grouped pieces to a piece not grouped"
        cur = self.db.cursor()

        (results, col_names) = rowify(cur.execute(self.query_puzzle_255),
                                      cur.description)
        testPuzzle = results[0]
        r = 0

        # Move piece 7
        (piece, x, y) = (7, 55, 118)
        (topic, msg) = translate(0,
                                 testPuzzle,
                                 piece,
                                 x,
                                 y,
                                 r,
                                 db_file=self.tmp_db.name)
        (piece, x, y) = (3, 46, 196)
        (topic, msg) = translate(0,
                                 testPuzzle,
                                 piece,
                                 x,
                                 y,
                                 r,
                                 db_file=self.tmp_db.name)
        # Piece 3 and 2 are grouped, 3 is moved to join piece 7
        expectedMsg = (
            ":{piece}:{x}:{y}:0:3:\n:7::::3:\n:2:120:183:::\n:3:55:183:0:3:".
            format(**locals()))
        assert len(expectedMsg) == len(msg)
        for l in expectedMsg.split("\n"):
            assert l in msg
Ejemplo n.º 16
0
    def test_updates_puzzle_details_with_values(self):
        "Should update the puzzle details with the values that were sent"
        with self.app.app_context():
            with self.app.test_client() as c:
                new_data = {"status": 1, "queue": 1, "pieces": 1234}
                rv = c.patch(
                    "/internal/puzzle/{puzzle_id}/details/".format(
                        puzzle_id=self.puzzle_id
                    ),
                    json=new_data,
                )
                self.assertEqual(200, rv.status_code)
                self.assertEqual(
                    {"msg": "Updated", "rowcount": 1, "status_code": 200}, rv.json
                )

                self.puzzle_data.update(new_data)

                cur = self.db.cursor()
                result = cur.execute(
                    fetch_query_string(
                        "select-internal-puzzle-details-for-puzzle_id.sql"
                    ),
                    {"puzzle_id": self.puzzle_id,},
                ).fetchall()
                (result, col_names) = rowify(result, cur.description)
                self.assertEqual(result[0], self.puzzle_data)
Ejemplo n.º 17
0
    def test_join_two_pieces_that_are_both_in_group(self):
        "Join two pieces that are grouped when moving piece group is smaller or same size"
        cur = self.db.cursor()

        (results, col_names) = rowify(cur.execute(self.query_puzzle_255),
                                      cur.description)
        testPuzzle = results[0]
        r = 0

        # Move piece 9 which is in group 10
        (piece, x, y) = (9, 809, 139)
        (topic, msg) = translate(0,
                                 testPuzzle,
                                 piece,
                                 x,
                                 y,
                                 r,
                                 db_file=self.tmp_db.name)

        # Move piece 2 to join piece 9; group 3 pieces are now in group 10
        (piece, x, y) = (2, 731, 140)
        (topic, msg) = translate(0,
                                 testPuzzle,
                                 piece,
                                 x,
                                 y,
                                 r,
                                 db_file=self.tmp_db.name)

        expectedMsg = ":{piece}:{x}:{y}:270:3:\n:3:679:139::10:\n:2::::10:\n:2:744:139:270:10:".format(
            **locals())
        assert len(expectedMsg) == len(msg)
        for l in expectedMsg.split("\n"):
            assert l in msg
Ejemplo n.º 18
0
    def post(self):
        args = {}
        xhr_data = request.get_json()
        if xhr_data:
            args.update(xhr_data)
        args.update(request.form.to_dict(flat=True))
        args.update(request.args.to_dict(flat=True))

        if len(args.keys()) == 0:
            abort(400)

        # Start db operations
        cur = db.cursor()

        llamas = 0
        result = cur.execute(fetch_query_string("get-llama-count.sql")).fetchall()
        if result:
            (result, col_names) = rowify(result, cur.description)
            llamas = result[0]["llamas"]

        # TODO: Process args for llamaness
        processed = {"llama-check": True, "count": llamas}

        db.commit()
        cur.close()

        return json.jsonify(processed)
Ejemplo n.º 19
0
    def test_join_two_pieces_that_are_both_in_group_when_adjacent_group_smaller(
            self):
        "Join two pieces that are grouped when moving piece group is larger then adjacent piece group"
        cur = self.db.cursor()

        (results, col_names) = rowify(cur.execute(self.query_puzzle_255),
                                      cur.description)
        testPuzzle = results[0]
        r = 0

        # Move piece 1 to join piece 10. Piece 1 is in larger group 8, and piece 10 is in smaller group 10
        # (1,8,11) (9,10)
        (piece, x, y) = (1, 499, 580)
        (topic, msg) = translate(0,
                                 testPuzzle,
                                 piece,
                                 x,
                                 y,
                                 r,
                                 db_file=self.tmp_db.name)

        expectedMsg = ":{piece}:{x}:{y}:0:8:\n:9::::8:\n:10::::8:\n:8:365:592:::\n:11:430:592:::\n:1:495:592:0:8:".format(
            **locals())
        assert len(expectedMsg) == len(msg)
        for l in expectedMsg.split("\n"):
            assert l in msg
Ejemplo n.º 20
0
    def __init__(self, ip):
        self.ip = ip
        self.headers = {"X-Real-IP": ip}

        self.api_host = "http://localhost:{PORTAPI}".format(
            PORTAPI=current_app.config["PORTAPI"])
        self.publish_host = "http://localhost:{PORTPUBLISH}".format(
            PORTPUBLISH=current_app.config["PORTPUBLISH"])

        cur = db.cursor()
        result = cur.execute(
            read_query_file("select-user-id-by-ip-and-no-password.sql"), {
                "ip": ip
            }).fetchall()
        if result:
            (result, col_names) = rowify(result, cur.description)
            shareduser = result[0]["id"]
            redis_connection.zrem("bannedusers", shareduser)
        cur.close()

        # get test user
        current_user_id = requests.get("{0}/current-user-id/".format(
            self.api_host),
                                       headers=self.headers)
        # print('ip {} and {}'.format(ip, current_user_id.cookies))
        self.shareduser_cookie = current_user_id.cookies["shareduser"]
        self.shareduser = int(current_user_id.content)
Ejemplo n.º 21
0
    def test_move_three_pieces_in_group(self):
        "Move three pieces that are grouped"
        cur = self.db.cursor()

        (results, col_names) = rowify(cur.execute(self.query_puzzle_255),
                                      cur.description)
        testPuzzle = results[0]
        r = 0

        (piece, x, y) = (11, 368, 31)
        (topic, msg) = translate(0,
                                 testPuzzle,
                                 piece,
                                 x,
                                 y,
                                 r,
                                 db_file=self.tmp_db.name)
        # Pieces 11, 1 and 8 are grouped. 11 gets moved and then the others move as well.
        expectedMsg = ":{piece}:{x}:{y}:90:8:\n:1:433:31:::\n:8:303:31:::".format(
            **locals())
        print("({0})".format(expectedMsg))
        print("[{0}]".format(msg))
        assert len(expectedMsg) == len(msg)
        for l in expectedMsg.split("\n"):
            assert l in msg
Ejemplo n.º 22
0
    def get_offset_of_adjacent_pieces(piece, mask_width, piece_width):
        cur = db.cursor()
        offsets = {}

        x = piece['x']
        y = piece['y']
        t = mask_width - piece_width
        sides = [
            {'side':{
                (360, 0):'top_path',
                },
              'other_side':{
                (360, 0):'bottom_path',
                },
              'x':x,
              'y':((y+t) - mask_width)},
             {'side':{
               (360, 0):'right_path',
               },
              'other_side':{
                (360, 0):'left_path',
                },
              'x':((x-t) + mask_width),
              'y':y},
             {'side':{
               (360, 0):'bottom_path',
               },
              'other_side':{
                (360, 0):'top_path',
                },
              'x':x,
              'y':((y-t) + mask_width)},
             {'side':{
               (360, 0):'left_path',
               },
              'other_side':{
                (360, 0):'right_path',
                },
              'x':((x+t) - mask_width),
              'y':(y)},
            ]
        piece_alignment = (360, 0)

        query = """select * from Piece where (id != :id) and (puzzle = :puzzle) and ((top_path = :bottom_path) or (bottom_path = :top_path) or (right_path = :left_path) or (left_path = :right_path))"""
        (d, col_names) = rowify(cur.execute(query, piece).fetchall(), cur.description)
        for adjacent_piece in d:
            for s in sides:
                try:
                    if adjacent_piece[s['other_side'][piece_alignment]] == piece[s['side'][piece_alignment]]: # always check if the sides match
                        offset = {
                            'x': int(math.ceil(piece_width)*FITS_MAPPING[s['side'][piece_alignment]]['x']),
                            'y': int(math.ceil(piece_width)*FITS_MAPPING[s['side'][piece_alignment]]['y'])
                            }
                        offsets[adjacent_piece['id']] = '{x},{y}'.format(**offset)
                        break
                except KeyError:
                    continue

        cur.close()
        return offsets
 def test_connection(self):
     "Connection to db"
     with self.app.app_context():
         with self.app.test_client():
             cursor = db.cursor()
             result = cursor.execute("select 'test' as test")
             (result, col_names) = rowify(result, cursor.description)
             assert result[0]["test"] == "test"
Ejemplo n.º 24
0
    def get(self, puzzle_id):
        """
        deletePenalty: number;
        canFreeze: boolean;
        canDelete: boolean;
        canReset: boolean;
        hasActions: boolean;
        deleteDisabledMessage: string; //Not enough dots to delete this puzzle
        isFrozen: boolean;
        status: number;
        """
        ip = request.headers.get("X-Real-IP")
        user = int(current_app.secure_cookie.get("user") or user_id_from_ip(ip))

        cur = db.cursor()

        # validate the puzzle_id
        result = cur.execute(
            fetch_query_string("select-puzzle-details-for-puzzle_id.sql"),
            {"puzzle_id": puzzle_id},
        ).fetchall()
        if not result:
            # 400 if puzzle does not exist
            err_msg = {
                "msg": "No puzzle found",
            }
            cur.close()
            return make_response(json.jsonify(err_msg), 400)
        (result, col_names) = rowify(result, cur.description)
        puzzleData = result[0]

        (delete_penalty, can_delete, delete_disabled_message) = self.get_delete_prereq(
            puzzleData
        )
        response = {
            "canDelete": can_delete,
            "canFreeze": puzzleData.get("status") in (FROZEN, BUGGY_UNLISTED, ACTIVE),
            "canReset": puzzleData.get("permission") == PRIVATE
            and not puzzleData.get("is_original")
            and puzzleData.get("status") in (FROZEN, BUGGY_UNLISTED, ACTIVE, COMPLETED),
            "hasActions": puzzleData.get("status")
            in (
                FROZEN,
                ACTIVE,
                COMPLETED,
                BUGGY_UNLISTED,
                RENDERING_FAILED,
                REBUILD,
                IN_RENDER_QUEUE,
                MAINTENANCE,
            ),
            "deleteDisabledMessage": delete_disabled_message,
            "deletePenalty": delete_penalty,
            "isFrozen": puzzleData.get("status") == FROZEN,
            "status": puzzleData.get("status", -99),
        }
        cur.close()
        return make_response(json.jsonify(response), 200)
Ejemplo n.º 25
0
def add_to_timeline(puzzle_id, player, points=0, timestamp=None, message=""):
    ""

    if timestamp is None:
        _timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
    else:
        # TODO: Should verify timestamp is in ISO format.
        _timestamp = timestamp

    if not isinstance(points, int):
        err_msg = {"msg": "points needs to be an integer", "status_code": 400}
        return err_msg

    cur = db.cursor()
    result = cur.execute(
        fetch_query_string("select-internal-puzzle-details-for-puzzle_id.sql"),
        {
            "puzzle_id": puzzle_id
        },
    ).fetchall()
    if not result:
        err_msg = {"msg": "No puzzle found", "status_code": 400}
        cur.close()
        return err_msg

    (result, col_names) = rowify(result, cur.description)
    puzzle_data = result[0]
    puzzle = puzzle_data["id"]

    # TODO: The message is not added to the Timeline DB table for now since that
    # information is not currently being used.
    try:
        result = cur.execute(
            fetch_query_string("insert_batchpoints_to_timeline.sql"),
            {
                "puzzle": puzzle,
                "player": player,
                "points": points,
                "timestamp": _timestamp,
            },
        )
    except sqlite3.IntegrityError:
        err_msg = {
            "msg":
            "Database integrity error. Does the player ({}) exist?".format(
                player),
            "status_code":
            400,
        }
        cur.close()
        return err_msg

    cur.close()
    db.commit()
    msg = {"rowcount": result.rowcount, "msg": "Inserted", "status_code": 200}
    return msg
Ejemplo n.º 26
0
def reset_puzzle_pieces_and_handle_errors(puzzle):
    cur = db.cursor()
    result = cur.execute(
        fetch_query_string("select_all_from_puzzle_for_id.sql"),
        {
            "id": puzzle
        },
    ).fetchall()
    if not result:
        cur.close()
        raise DataError("No puzzle found with that id.")

    (result, col_names) = rowify(result, cur.description)
    puzzle_data = result[0]
    cur.close()

    try:
        reset_puzzle_pieces(puzzle)
    # TODO: Fix handling of errors on puzzle reset pieces
    except Error as err:
        # Update puzzle status to RENDERING_FAILED
        r = requests.patch(
            "http://{HOSTAPI}:{PORTAPI}/internal/puzzle/{puzzle_id}/details/".
            format(
                HOSTAPI=current_app.config["HOSTAPI"],
                PORTAPI=current_app.config["PORTAPI"],
                puzzle_id=puzzle_data["puzzle_id"],
            ),
            json={"status": RENDERING_FAILED},
        )
        sse.publish(
            "status:{}".format(RENDERING_FAILED),
            channel="puzzle:{puzzle_id}".format(
                puzzle_id=puzzle_data["puzzle_id"]),
        )
        if r.status_code != 200:
            raise Exception("Puzzle details api error")

    # Update puzzle status to ACTIVE and sse publish
    r = requests.patch(
        "http://{HOSTAPI}:{PORTAPI}/internal/puzzle/{puzzle_id}/details/".
        format(
            HOSTAPI=current_app.config["HOSTAPI"],
            PORTAPI=current_app.config["PORTAPI"],
            puzzle_id=puzzle_data["puzzle_id"],
        ),
        json={"status": ACTIVE},
    )
    sse.publish(
        "status:{}".format(ACTIVE),
        channel="puzzle:{puzzle_id}".format(
            puzzle_id=puzzle_data["puzzle_id"]),
    )
    if r.status_code != 200:
        raise Exception("Puzzle details api error")
Ejemplo n.º 27
0
 def __init__(self, puzzle_id, ip):
     self.puzzle_id = puzzle_id
     self.ip = ip
     cur = db.cursor()
     result = cur.execute(
         "select id, table_width, table_height from Puzzle where puzzle_id = :puzzle_id;",
         {
             "puzzle_id": self.puzzle_id
         },
     ).fetchall()
     (result, col_names) = rowify(result, cur.description)
     self.puzzle_details = result[0]
     cur.close()
Ejemplo n.º 28
0
 def __init__(self, puzzle_id, ips, max_delay=0.1):
     self.puzzle_id = puzzle_id
     self.ips = ips
     self.max_delay = max_delay
     self.user_sessions = list(map(lambda ip: UserSession(ip=ip), self.ips))
     cur = db.cursor()
     result = cur.execute(
         "select id, table_width, table_height from Puzzle where puzzle_id = :puzzle_id;",
         {
             "puzzle_id": self.puzzle_id
         },
     ).fetchall()
     (result, col_names) = rowify(result, cur.description)
     self.puzzle_details = result[0]
     cur.close()
     redis_connection.delete("testdata:too_active")
Ejemplo n.º 29
0
 def get(self, user):
     cur = db.cursor()
     result = cur.execute(
         fetch_query_string("select-user-details-by-id.sql"),
         {
             "id": user,
         },
     ).fetchall()
     if not result:
         err_msg = {
             "msg": "No user found",
         }
         cur.close()
         return make_response(json.jsonify(err_msg), 404)
     (result, col_names) = rowify(result, cur.description)
     user_details = result[0]
     return make_response(json.jsonify(user_details), 200)
Ejemplo n.º 30
0
    def get(self, anonymous_login):
        "Set the user cookie if correct anon bit link."
        login = anonymous_login[:-13]
        password = anonymous_login[-13:]
        cur = db.cursor()

        response = make_response(redirect("/"))

        result = cur.execute(fetch_query_string("select-user-by-login.sql"), {
            "login": login
        }).fetchall()

        if not result:
            cur.close()
            return make_response("no user", 404)

        (result, col_names) = rowify(result, cur.description)
        user_data = result[0]

        expires = datetime.datetime.utcnow() - datetime.timedelta(days=365)
        if crypt.crypt(password,
                       user_data["password"]) == user_data["password"]:
            current_app.secure_cookie.set("shareduser",
                                          "",
                                          response,
                                          expires=expires)
            current_app.secure_cookie.set("user",
                                          str(user_data["id"]),
                                          response,
                                          expires_days=365)
            cur.execute(
                fetch_query_string("extend-cookie_expires-for-user.sql"),
                {"id": user_data["id"]},
            )
            db.commit()
        else:
            # Invalid anon login; delete cookie just in case it's there
            current_app.secure_cookie.set("user",
                                          "",
                                          response,
                                          expires=expires)

        cur.close()

        return response