示例#1
0
    def test_load_modify_save(self, test_app_context, fixture_colony_a):

        ad = fixture_colony_a.to_dict()

        connection = get_redis_db_from_context()

        # It should be near the end of the list.
        index = connection.lrange(consts.KEY_COLONY_INDEX_BY_ID, -5, -1)

        assert fixture_colony_a.Hash in index

        # Reload it as a new object
        b = Colony.get_from_database(ad, db.get_redis_db_from_context())

        assert b.Hash == fixture_colony_a.Hash

        for k, v in b.to_dict().items():
            assert ad[k] == v

        b.LastAction = 2

        b.save_to_database(connection)

        c = Colony.get_from_database(ad, db.get_redis_db_from_context())

        assert c.LastAction == b.LastAction
示例#2
0
    def test_one_doesnt_exist(self, test_app_context, fixture_colony_a,
                              fixture_colony_b):
        connection = get_redis_db_from_context()

        a = fixture_colony_a
        b = fixture_colony_b

        self.setup_data_in_db(a, connection)
        self.setup_data_in_db(b, connection)

        c = Colony.from_dict(
            {
                'BaseName': 'TestColonyC',
                'FactionName': 'TestFactionC',
                'Planet': 'TestPlanetC',
                'Hash': 'EFGH',
                'OwnerType': 'Normal',
                'OwnerID': 1
            },
            connection=db.get_redis_db_from_context())
        colony_data = [a.to_dict(), b.to_dict(), c.to_dict()]

        result = list(
            Colony.get_many_from_database(
                colony_data, db.get_redis_db_from_context()).values())

        assert len(result) == 3
        assert result[0].BaseName == a.BaseName and result[0].FromDatabase
        assert result[1].BaseName == b.BaseName and result[1].FromDatabase
        assert result[2].BaseName == c.BaseName and not result[2].FromDatabase
示例#3
0
    def test_save_and_load_steam(self, test_app_context, fixture_colony_steam):

        connection = get_redis_db_from_context()

        self.setup_data_in_db(fixture_colony_steam, connection)

        # It should be near the end of the list.
        index = connection.lrange(consts.KEY_COLONY_INDEX_BY_ID, -5, -1)

        steam_index = connection.lrange(
            consts.KEY_COLONY_INDEX_BY_STEAM_ID.format(
                fixture_colony_steam.OwnerID), -5, -1)

        assert fixture_colony_steam.Hash in index
        assert fixture_colony_steam.Hash in steam_index

        # Reload it as a new object
        o_loaded = Colony.get_from_database(fixture_colony_steam.to_dict(),
                                            db.get_redis_db_from_context())

        assert o_loaded.FromDatabase
        assert o_loaded.Hash == fixture_colony_steam.Hash

        od = fixture_colony_steam.to_dict()

        for k, v in o_loaded.to_dict().items():
            assert od[k] == v
示例#4
0
    def test_class_init_from_dict_hash(self, test_app_context,
                                       fixture_colony_a):

        o = Colony.from_dict(fixture_colony_a.to_dict(),
                             db.get_redis_db_from_context())

        assert "87a41f64617b379cb80c7123351b35db356c97c8" == o.Hash
示例#5
0
    def test_get_colony_by_hash(self, test_app_context, fixture_colony_steam):
        connection = get_redis_db_from_context()
        self.setup_data_in_db(fixture_colony_steam, connection)

        result = Colony.get_from_database_by_hash(
            fixture_colony_steam.Hash, db.get_redis_db_from_context())

        assert result.FromDatabase
示例#6
0
    def test_class_init_from_dict_to_dict(self, test_app_context,
                                          fixture_colony_a):

        a_dict = fixture_colony_a.to_dict()
        b = Colony.from_dict(a_dict, db.get_redis_db_from_context()).to_dict()

        for k, v in b.items():
            assert a_dict[k] == v
示例#7
0
    def test_all_none(self, test_app_context):
        """
        Test that none of these entries exist in the DB,
        Assert that all results have FromDatabase == False
        :param test_app_context:
        :return:
        """
        a = Colony.from_dict(
            {
                'BaseName': 'TestColonyA',
                'FactionName': 'TestFactionA',
                'Planet': 'TestPlanetA',
                'Hash': '1234',
                'OwnerType': 'Normal',
                'OwnerID': 1
            },
            connection=db.get_redis_db_from_context())
        b = Colony.from_dict(
            {
                'BaseName': 'TestColonyB',
                'FactionName': 'TestFactionB',
                'Planet': 'TestPlanetB',
                'Hash': '5678',
                'OwnerType': 'Normal',
                'OwnerID': 1
            },
            connection=db.get_redis_db_from_context())
        c = Colony.from_dict(
            {
                'BaseName': 'TestColonyC',
                'FactionName': 'TestFactionC',
                'Planet': 'TestPlanetC',
                'Hash': 'EFGH',
                'OwnerType': 'Normal',
                'OwnerID': 1
            },
            connection=db.get_redis_db_from_context())
        colony_data = [a.to_dict(), b.to_dict(), c.to_dict()]
        result = Colony.get_many_from_database(colony_data,
                                               db.get_redis_db_from_context())
        s = list(zip(colony_data, result.values()))

        assert len(s) == 3
        for a, b in s:
            assert not b.FromDatabase
示例#8
0
def new_colony_from_request(incoming_data, connection):
    new_colony = {
        'BaseName': escape(incoming_data['BaseName']),
        'FactionName': escape(incoming_data['FactionName']),
        'Planet': escape(incoming_data['Planet']),
        'OwnerType': escape(incoming_data['OwnerType']),
        'OwnerID': escape(incoming_data['OwnerID']),
        'LastGameTick': escape(incoming_data['LastGameTick'])
    }

    return Colony.from_dict(new_colony, connection=connection)
示例#9
0
def colony_get_data(colony_hash):
    print("Getting colony data")
    colony = Colony.get_from_database_by_hash(colony_hash,
                                              db.get_redis_db_from_context())

    if not colony:
        return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND)
    print("Sending colony data")
    return Response(json.dumps(colony.to_dict()),
                    status=200,
                    mimetype='application/json')
示例#10
0
 def fixture_colony_steam() -> Colony:
     s: Colony = Colony.from_dict(
         {
             'BaseName': 'TestColonyS',
             'FactionName': 'TestFactionS',
             'Planet': 'TestPlanetS',
             'DateCreated': 100,
             'OwnerType': 'Steam',
             'OwnerID': '76561198275909496'
         },
         connection=db.get_redis_db_from_context())
     return s
示例#11
0
 def fixture_colony_b() -> Colony:
     b: Colony = Colony.from_dict(
         {
             'BaseName': 'TestColonyB',
             'FactionName': 'TestFactionB',
             'Planet': 'TestPlanetB',
             'Hash': 'ABCD',
             'OwnerType': 'Normal',
             'OwnerID': 1
         },
         connection=db.get_redis_db_from_context())
     return b
示例#12
0
 def fixture_colony_a() -> Colony:
     a: Colony = Colony.from_dict(
         {
             'BaseName': 'TestColonyA',
             'FactionName': 'TestFactionA',
             'Planet': 'TestPlanetA',
             'DateCreated': 1,
             'OwnerType': 'Normal',
             'OwnerID': 1
         },
         connection=db.get_redis_db_from_context())
     return a
示例#13
0
def subscription_update(colony_hash):
    db_connection = db.get_redis_db_from_context()

    colony = Colony.get_from_database_by_hash(colony_hash, db.get_redis_db_from_context())

    if not colony:
        current_app.logger.warning('{} colony not found in database'.format(colony.Hash))
        return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND)

    sub_data = request.json

    # Validate token
    if 'Token' not in sub_data:
        current_app.logger.error('{} Subscription token was not in payload.'.format(colony.Hash))
        return Response(consts.ERROR_INVALID, status=consts.HTTP_INVALID)

    # Fetch our token from DB
    token_in_db = db_connection.get(consts.KEY_PRIME_TOKEN_DATA.format(colony.Hash))

    # Has it expired or ever existed?
    if token_in_db is None:
        current_app.logger.warning('{} Subscription token was not in database or has expired.'.format(colony.Hash))
        return Response(consts.ERROR_INVALID, status=consts.HTTP_INVALID)

    # They should match
    if token_in_db != sub_data['Token']:
        current_app.logger.error(
            '{} Subscription tokens did not match {} != {}.'.format(colony.Hash, sub_data['Token'], token_in_db))
        return Response(consts.ERROR_INVALID, status=consts.HTTP_INVALID)

    expiryTick = DaysPerQuadrum * TicksPerDay + colony.LastGameTick

    pipe = db_connection.pipeline()
    # Update subscription tick for Colony.
    pipe.set(consts.KEY_PRIME_SUBSCRIPTION_DATA.format(colony.Hash), int(expiryTick))

    # Remove the token to prevent reuse.
    pipe.delete(consts.KEY_PRIME_TOKEN_DATA.format(colony_hash))

    # Subscriptions expire after 42 days in real life.
    pipe.expireat(consts.KEY_PRIME_SUBSCRIPTION_DATA.format(colony.Hash),
                  date_utils.add_days_to_current_time(30))

    # Update Silver acquired.
    thing = Thing("Silver")
    subscriptionCost = int(db_connection.get(consts.KEY_CONFIGURATION_PRIME_COST))
    pipe.hincrby(consts.KEY_THING_META.format(thing.Hash), 'Quantity', subscriptionCost)
    pipe.execute()
    current_app.logger.debug('{} Subscription successful.'.format(colony.Hash))
    return Response("OK", status=consts.HTTP_OK)
示例#14
0
    def setup_data_in_db(colony: Colony, connection):

        do_exec = False

        if not isinstance(connection, redis.client.Pipeline):
            connection = connection.pipeline()
            do_exec = True

        connection.delete(consts.KEY_COLONY_METADATA.format(colony.Hash))

        # Remove the key from the index if it already exists
        connection.lrem(consts.KEY_COLONY_INDEX_BY_ID, 0, colony.Hash)

        # Remove key from Steam User keys
        if colony.OwnerType == 'Steam':
            connection.lrem(
                consts.KEY_COLONY_INDEX_BY_STEAM_ID.format(colony.OwnerID), 0,
                colony.Hash)

        # Write the Colony to the database.
        colony.save_to_database(connection)

        if do_exec:
            connection.execute()
示例#15
0
def colony_update_data(colony_hash):
    connection = db.get_redis_db_from_context()
    colony = Colony.get_from_database_by_hash(colony_hash, connection)

    print("Saving colony data")
    incoming_data = request.json

    created = False

    if not colony or colony.OwnerID != incoming_data['OwnerID']:
        # If the Owner ID's don't match. Create a new colony.
        # And assign it a new ID. Might have happened if save sharing.
        colony = new_colony_from_request(incoming_data, connection)
        created = True
    else:
        colony.BaseName = escape(incoming_data['BaseName'])
        colony.FactionName = escape(incoming_data['FactionName'])
        colony.Planet = escape(incoming_data['Planet'])
        colony.LastGameTick = escape(incoming_data['LastGameTick'])
        if incoming_data['HasSpawned']:
            colony.Ban()

    pipe = connection.pipeline()

    if colony.IsBanned():
        return Response(consts.ERROR_BANNED, status=consts.HTTP_FORBIDDEN)

    # Make sure add the owners to the correct sets.
    if colony.OwnerType == 'Steam':
        key = consts.KEY_USER_INDEX_BY_STEAM_ID
    elif colony.OwnerType == 'Normal':
        key = consts.KEY_USER_INDEX_BY_NORMAL_ID
    else:
        return Response(consts.ERROR_INVALID, status=consts.HTTP_INVALID)

    pipe.sadd(key, colony.OwnerID)

    colony.save_to_database(pipe)

    pipe.execute()

    colony.ping()
    print("Sending colony hash")
    return Response(json.dumps({'Hash': colony.Hash}),
                    status=201 if created else 200,
                    mimetype='application/json')
示例#16
0
def colony_set_supported_things(colony_hash: str):
    print("Received Supported things list from colony")

    colony = Colony.get_from_database_by_hash(colony_hash,
                                              db.get_redis_db_from_context())
    if not colony:
        return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND)

    try:
        gz_post_data = request.files['things']

        # Decompress payload
        thing_file = gzip.GzipFile(fileobj=gz_post_data, mode='r')

        # Deserialize JSON back in to {'Locale': str, 'Things': List[Dict[str, str]]}
        payload = json.loads(thing_file.read().decode('UTF8'))

        # Set locale
        locale = payload['Locale'].lower()

        # This is a List[Dict[str, str]]
        supported_things_json = payload['Things']

        print("Supported things parsed")

    except json.JSONDecodeError:
        print("Error in things list found")
        return Response(consts.ERROR_INVALID, status=consts.HTTP_INVALID)

    # Need to construct things then add Localized name to index
    pipe = db.get_redis_db_from_context().pipeline()

    pipe.sadd(consts.KEY_THING_LOCALE_KNOWN_LANGUAGES, locale)

    for thing_json in supported_things_json:
        thing = Thing.from_dict(thing_json)
        pipe.zincrby(KEY_THING_LOCALE_THING_NAMES.format(locale, thing.Hash),
                     1, thing.LocalizedName)
    pipe.execute()

    # This is immediately saved.
    colony.SupportedThings = supported_things_json
    print("Supported things saved")
    return Response('OK', status=200, mimetype='application/json')
示例#17
0
def colony_set_mods(colony_hash: str):
    print("Received List of Mods from colony")
    colony = Colony.get_from_database_by_hash(colony_hash,
                                              db.get_redis_db_from_context())
    if not colony:
        return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND)

    try:
        gz_post_data = request.files['mods']
        mod_file = gzip.GzipFile(fileobj=gz_post_data, mode='r')
        payload = json.loads(mod_file.read().decode('UTF8'))
        mod_list = payload['ModList']

    except json.JSONDecodeError:
        print("Error in mod list found")
        return Response(consts.ERROR_INVALID, status=consts.HTTP_INVALID)

    # This is immediately saved.
    colony.ModList = mod_list
    print("List of Mods Saved")
    return Response('OK', status=200, mimetype='application/json')
示例#18
0
def market_get_items(colony_hash):
    print("Sending Market items to Colony")
    connection = db.get_redis_db_from_context()
    colony = Colony.get_from_database_by_hash(colony_hash,
                                              db.get_redis_db_from_context())
    if not colony:
        return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND)

    things = Thing.get_many_from_database(colony.SupportedThings, connection)

    #thing_data = [thing.to_dict() for thing in things.values()]
    thing_data = [
        thing.to_dict() for thing in things.values() if thing.Quantity > 0
    ]
    print("Market items sent")

    content = gzip.compress(json.dumps(thing_data).encode('utf8'), 5)
    response = make_response(content, 200)
    response.headers['Content-length'] = len(content)
    response.headers['Content-Encoding'] = 'gzip'
    response.headers['Content-Type'] = "application/json"
    return response
示例#19
0
    def test_all_exist(self, test_app_context, fixture_colony_a,
                       fixture_colony_b, fixture_colony_steam):

        connection = get_redis_db_from_context()

        a = fixture_colony_a
        b = fixture_colony_b
        c = fixture_colony_steam

        self.setup_data_in_db(a, connection)
        self.setup_data_in_db(b, connection)
        self.setup_data_in_db(c, connection)

        colony_data = [a.to_dict(), b.to_dict(), c.to_dict()]

        result = Colony.get_many_from_database(colony_data,
                                               db.get_redis_db_from_context())

        s = zip(colony_data, result.values())

        for a, b in s:
            assert a['BaseName'] == b.BaseName and b.FromDatabase
示例#20
0
def subscription_check(colony_hash):
    print("Checking subscription status for colony")
    db_connection = db.get_redis_db_from_context()
    response = dict()

    colony = Colony.get_from_database_by_hash(colony_hash, db.get_redis_db_from_context())

    if not colony:
        print("Colony does not exist in db")
        current_app.logger.error('{} colony not found in database'.format(colony.Hash))
        return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND)

    response['SubscriptionCost'] = int(db_connection.get(consts.KEY_CONFIGURATION_PRIME_COST))

    # 0 ticks left unless we get a score back from the sorted set.
    response['TickSubscriptionExpires'] = 0

    ticks_remaining = db_connection.get(consts.KEY_PRIME_SUBSCRIPTION_DATA.format(colony.Hash))

    if ticks_remaining is not None:
        response['TickSubscriptionExpires'] = int(ticks_remaining)
    else:
        response['TickSubscriptionExpires'] = 0

    current_app.logger.debug('{} is generating a subscription token.'.format(colony.Hash))
    # Generate a random token only valid for 30 seconds.
    token = make_token(colony.Hash)
    pipe = db_connection.pipeline()
    pipe.set(consts.KEY_PRIME_TOKEN_DATA.format(colony.Hash), token)
    pipe.expire(consts.KEY_PRIME_TOKEN_DATA.format(colony.Hash), 30)
    pipe.execute()
    response['Token'] = token
    current_app.logger.debug('{} new token is .'.format(colony.Hash, token))

    print("Subscription status sent to colony")
    return Response(json.dumps(response), status=200, mimetype='application/json')