def default_search(): listUsersResponse = account_utils.get_user_pool_client().list_users( UserPoolId=account_utils.get_user_pool_id(), Limit=50) usersByName = { user.get('Username', ''): user for user in listUsersResponse.get('Users', []) } accounts = [] scanResponse = account_utils.get_account_table().scan(Limit=50) for accountItem in scanResponse.get('Items', []): account = account_utils.convert_account_from_dynamo_to_admin_model( accountItem) username = account.get('CognitoUsername') if username: user = usersByName.get(username) if user: account['IdentityProviders'] = { account_utils.IDP_COGNITO: account_utils.convert_user_from_cognito_to_model(user) } del usersByName[username] else: populate_identity_provider(account) accounts.append(account) for username, user in usersByName.iteritems(): account = populate_account_for_user(user) accounts.append(account) accounts.sort(cmp=account_utils.compare_accounts) return {'Accounts': accounts}
def get(request, AccountId): response = account_utils.get_account_table().get_item(Key = { 'AccountId': AccountId }, ConsistentRead = False) if not 'Item' in response: raise errors.ClientError("No account found for '{}'".format(AccountId)) account = account_utils.convert_account_from_dynamo_to_admin_model(response['Item']) load_user(account) return account
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_cognito_identity_id(CognitoIdentityId): response = account_utils.get_account_table().query( ConsistentRead=False, IndexName='CognitoIdentityIdIndex', KeyConditionExpression=Key('CognitoIdentityId').eq(CognitoIdentityId)) accounts = [] for item in response.get('Items', []): accounts.append( account_utils.convert_account_from_dynamo_to_admin_model(item)) populate_identity_providers(accounts) return {'Accounts': accounts}
def get_accounts_by_username(Username): response = account_utils.get_account_table().query( ConsistentRead=False, IndexName='CognitoUsernameIndex', KeyConditionExpression=Key('CognitoUsername').eq(Username)) accounts = [] for item in response.get('Items', []): accounts.append( account_utils.convert_account_from_dynamo_to_admin_model(item)) populate_identity_providers(accounts) return accounts
def get(request): if not request.event["cognitoIdentityId"]: raise errors.ForbiddenRequestError('The credentials used did not contain Cognito identity information') account = account_utils.get_account_for_identity(request.event["cognitoIdentityId"]) if not account: raise errors.ClientError("No account found for '{}'".format(request.event["cognitoIdentityId"])) if account.get('AccountBlacklisted'): raise errors.ForbiddenRequestError('The account is blacklisted') response = account_utils.get_account_table().get_item(Key = { 'AccountId': account['AccountId'] }, ConsistentRead = False) if not 'Item' in response: raise errors.ClientError("No account found for '{}'".format(account['AccountId'])) return account_utils.convert_account_from_dynamo_to_player_model(response['Item'])
def undo_account_changes(AccountId, account_was_created, existingAccount, accountUpdates): if account_was_created: response = account_utils.get_account_table().delete_item(Key={'AccountId': AccountId}, ReturnValues='ALL_OLD') print 'Rolled back account creation for {}'.format(response.get('Attributes')) else: delete_keys = set() account_rollback = {} for k,v in accountUpdates.iteritems(): if k in existingAccount: account_rollback[k] = existingAccount[k] else: delete_keys.add(k) account_rollback['AccountId'] = AccountId account_utils.update_account(account_rollback, delete_keys) print 'Rolled back account changes.'
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
def put_account(AccountId, AccountRequest, create_account): account_utils.validate_account_update_request(AccountRequest) # Collect the attribute changes for the Cognito user. cognito_request = AccountRequest.get('IdentityProviders', {}).get(account_utils.IDP_COGNITO, {}) cognito_updates = get_cognito_updates(cognito_request) # Get the existing account if needed and determine the Cognito username. create_user = False existing_account = {} username = None if create_account: username = AccountRequest.get('CognitoUsername') create_user = '******' in AccountRequest else: existing_account = account_utils.get_account_table().get_item(Key = { 'AccountId': AccountId }, ConsistentRead = False).get('Item', {}) username = existing_account.get('CognitoUsername') if 'CognitoUsername' in AccountRequest and 'CognitoUsername' in existing_account and username != AccountRequest.get('CognitoUsername'): raise errors.ClientError('Changing the account username is not supported.') create_user = '******' in AccountRequest and 'CognitoUsername' not in existing_account if cognito_updates and not username: raise errors.ClientError('Unable to update Cognito: There is no Cognito user associated with this account.') # Collect the attribute changes for the account row. account_updates, delete_keys, added_to_blacklist = get_account_updates(AccountRequest, existing_account) # Create or update the account. updated_account = None account = account_updates.copy() account['AccountId'] = AccountId if create_account: account_utils.create_account(account) updated_account = account print 'Created account: ', account elif account_updates or delete_keys: updated_account = account_utils.update_account(account, delete_keys, existing_account) print 'Updated account: ', account # Create or update the Cognito user, and roll back the account changes if that fails. try: if create_user: account_utils.get_user_pool_client().admin_create_user( UserPoolId=account_utils.get_user_pool_id(), Username=username, UserAttributes=cognito_updates, DesiredDeliveryMediums=['EMAIL'] ) print 'Created: ', account_utils.logging_filter(cognito_updates) elif cognito_updates: account_utils.get_user_pool_client().admin_update_user_attributes( UserPoolId=account_utils.get_user_pool_id(), Username=username, UserAttributes=cognito_updates ) print 'Updated: ', account_utils.logging_filter(cognito_updates) except botocore.exceptions.ClientError as e: if updated_account: undo_account_changes(AccountId, create_account, existing_account, account_updates) code = e.response.get('Error', {}).get('Code', None) if code == 'UserNotFoundException': raise errors.ClientError('User does not exist in Cognito.') if code == 'UsernameExistsException': raise errors.ClientError('The username already exists in Cognito.') raise except: if updated_account: undo_account_changes(AccountId, create_account, existing_account, account_updates) raise if added_to_blacklist and username: # Invalidate existing tokens for the user after adding to the blacklist. account_utils.get_user_pool_client().admin_user_global_sign_out(UserPoolId=account_utils.get_user_pool_id(), Username=username) account = account_utils.convert_account_from_dynamo_to_admin_model(updated_account or existing_account) load_user(account) return account