Beispiel #1
0
def get_account_updates(account_request, existing_account):
    account_updates = {}
    delete_keys = set()
    if 'PlayerName' in account_request and existing_account.get(
            'PlayerName') != account_request.get('PlayerName'):
        # IndexedPlayerName and PlayerNameSortKey are used to search accounts by name, case insensitive.  See accountsearch.py
        account_updates['PlayerName'] = account_request['PlayerName']
        account_updates['IndexedPlayerName'] = account_request[
            'PlayerName'].lower()
        account_updates['PlayerNameSortKey'] = randint(
            1, account_utils.get_name_sort_key_count())

    request_account_blacklisted = bool(
        account_request.get('AccountBlacklisted'))
    added_to_blacklist = False
    if 'AccountBlacklisted' in account_request and bool(
            existing_account.get(
                'AccountBlacklisted')) != request_account_blacklisted:
        if request_account_blacklisted:
            account_updates['AccountBlacklisted'] = True
            added_to_blacklist = True
        else:
            delete_keys.add('AccountBlacklisted')

    if 'CognitoUsername' in account_request and existing_account.get(
            'CognitoUsername') != account_request.get('CognitoUsername'):
        account_updates['CognitoUsername'] = account_request['CognitoUsername']

    return account_updates, delete_keys, added_to_blacklist
Beispiel #2
0
def put(request, UpdateAccountRequest):
    if not request.event["cognitoIdentityId"]:
        raise errors.ForbiddenRequestError(
            'The credentials used did not contain Cognito identity information'
        )

    account_utils.validate_account_update_request(UpdateAccountRequest)

    account = account_utils.get_account_for_identity(
        request.event["cognitoIdentityId"])

    if not account:
        account = {
            'AccountId': str(uuid.uuid4()),
            'CognitoIdentityId': request.event["cognitoIdentityId"]
        }

        if 'PlayerName' in UpdateAccountRequest:
            # IndexedPlayerName and PlayerNameSortKey are used to search accounts by name, case insensitive.  See accountsearch.py
            account['PlayerName'] = UpdateAccountRequest['PlayerName']
            account['IndexedPlayerName'] = UpdateAccountRequest[
                'PlayerName'].lower()
            account['PlayerNameSortKey'] = randint(
                1, account_utils.get_name_sort_key_count())

        account_utils.create_account(account)
        return account_utils.convert_account_from_dynamo_to_player_model(
            account)
    else:
        if account.get('AccountBlacklisted'):
            raise errors.ForbiddenRequestError('The account is blacklisted')

        updateRequest = {'AccountId': account['AccountId']}

        if 'PlayerName' in UpdateAccountRequest:
            # IndexedPlayerName and PlayerNameSortKey are used to search accounts by name, case insensitive.  See accountsearch.py
            updateRequest['PlayerName'] = UpdateAccountRequest['PlayerName']
            updateRequest['IndexedPlayerName'] = UpdateAccountRequest[
                'PlayerName'].lower()
            updateRequest['PlayerNameSortKey'] = randint(
                1, account_utils.get_name_sort_key_count())

        result = account_utils.update_account(updateRequest)
        return account_utils.convert_account_from_dynamo_to_player_model(
            result)
def search_by_start_name(StartPlayerName):
    sortKeyCount = account_utils.get_name_sort_key_count()
    limit = 20

    accounts = []

    # Accounts are randomly split across multiple partition keys in accounts.py to distribute load on the index.
    # This will collect results from all of the keys and combine them.
    for partition in range(1, sortKeyCount + 1):
        # The query limit is set to the same limit as the number of returned accounts in case the results all come from
        # the same partition key.  An eventually consistent query consumes half a unit per 4KB regardless of how
        # many items contributed to the 4KB, so it's not too inefficient to read a lot of small items and throw most of them away.
        # This implementation expects searches to be relatively infrequent.
        queryArgs = {
            'ConsistentRead': False,
            'IndexName': 'PlayerNameIndex',
            'KeyConditionExpression': Key('PlayerNameSortKey').eq(partition),
            'Limit': limit,
            'ScanIndexForward': True
        }

        if StartPlayerName:
            # Convert the inclusive start key from the request into an exclusive start key since Dynamo only supports exclusive.
            # Dynamo sorts keys by utf-8 bytes.  This attempts to decrement the last byte so that it's one before
            # the start name.  Not guaranteed to work in all cases.
            exclusiveStartKeyBytes = bytearray(StartPlayerName.lower(),
                                               'utf-8')
            if exclusiveStartKeyBytes[-1] > 0:
                exclusiveStartKeyBytes[-1] = exclusiveStartKeyBytes[-1] - 1
            exclusiveStartKey = exclusiveStartKeyBytes.decode(
                'utf-8', 'ignore')

            queryArgs['ExclusiveStartKey'] = {
                'PlayerNameSortKey': partition,
                'IndexedPlayerName': exclusiveStartKey,
                'AccountId': ' '
            }
        response = account_utils.get_account_table().query(**queryArgs)

        for item in response.get('Items', []):
            accounts.append(
                account_utils.convert_account_from_dynamo_to_admin_model(item))

    accounts.sort(cmp=account_utils.compare_accounts)
    if len(accounts) > limit:
        del accounts[limit:]

    populate_identity_providers(accounts)

    return {'Accounts': accounts}
def search_by_start_name(start_player_name=None, serialized_page_token=None):
    page_size = 20

    config = dynamodb_pagination.PartitionedIndexConfig(
        table=account_utils.get_account_table(),
        index_name='PlayerNameIndex',
        partition_key_name='PlayerNameSortKey',
        sort_key_name='IndexedPlayerName',
        partition_count=account_utils.get_name_sort_key_count(),
        required_fields={'AccountId': ' '})

    if serialized_page_token:
        page_token = dynamodb_pagination.PageToken(config,
                                                   serialized_page_token)
    else:
        page_token = dynamodb_pagination.get_page_token_for_inclusive_start(
            config, start_player_name, forward=True)

    search = dynamodb_pagination.PaginatedSearch(config, page_token,
                                                 start_player_name)

    raw_account_items = search.get_next_page(page_size)

    accounts = [
        account_utils.convert_account_from_dynamo_to_admin_model(item)
        for item in raw_account_items
    ]
    populate_identity_providers(accounts)

    result = {'Accounts': accounts}

    forward_token = search.get_page_token(forward=True)
    if forward_token:
        result['next'] = forward_token

    backward_token = search.get_page_token(forward=False)
    if backward_token:
        result['previous'] = backward_token

    return result