Esempio n. 1
0
    def save(lists: ListDocModel) -> None:
        lists_table().put_item(
            Item=lists.dict(),
        )

        UserToLists.add_list(lists.userId, lists.id)
        for guest_id in lists.guests:
            UserToLists.add_list(guest_id, lists.id)
Esempio n. 2
0
def test_lists_dto_get__if_list_exists__and_user_is_not_an_owner__and_user_is_not_in_guests_list__raise_no_access_error(
        dynamodb_lists_table, sample_data):
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.clients.dynamodb import lists_table

    list1 = sample_data['lists'][1]

    lists_table().put_item(Item=list1)

    with pytest.raises(NoAccessError):
        ListsDto.get(list1['id'], '1d564127-9f04-47d4-a60c-61e4b8b6cb31')
Esempio n. 3
0
def test_lists_dto_get__if_list_exists__and_user_is_in_guests_list__return_the_list(
        dynamodb_lists_table, sample_data):
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.clients.dynamodb import lists_table

    list1 = sample_data['lists'][1]

    lists_table().put_item(Item=list1)

    res = ListsDto.get(list1['id'], list1['guests'][0])
    assert ListMappers.map_dto_to_doc(res) == ListDocModel.from_db_doc(list1)
Esempio n. 4
0
def test_lists_dto_update__when_user_has_no_access__raise_no_access_error(
        dynamodb_lists_table, sample_data):
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.clients.dynamodb import lists_table

    list2 = sample_data['lists'][2]
    lists_table().put_item(Item=list2)

    new_list = ListModel.parse_obj(list2)

    with pytest.raises(NoAccessError):
        ListsDto.update(new_list.id, new_list, tested_user_id)
Esempio n. 5
0
def test_lists_dto_update_item__when_user_has_no_access__raise_not_found_error(
        dynamodb_lists_table, sample_data):
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.clients.dynamodb import lists_table

    list0 = copy.deepcopy(sample_data['lists'][0])
    list0['userId'] = 'other_user_id'

    lists_table().put_item(Item=list0)

    with pytest.raises(NotFoundError):
        ListsDto.update_item(list0['id'], 0, 'item2', tested_user_id)
Esempio n. 6
0
def test_lists_dto_remove_item__when_user_is_guest__update_the_list(
        dynamodb_lists_table, sample_data):
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.clients.dynamodb import lists_table

    list1 = sample_data['lists'][1]
    lists_table().put_item(Item=list1)
    list_id = list1['id']
    item = list1['items'][0]
    res = ListsDto.remove_item(list_id, 0, tested_user_id)

    res_saved = lists_table().get_item(Key={'id': list_id})

    assert item not in res
    assert item not in res_saved['Item']['items']
Esempio n. 7
0
def test_lists_dto_get_all__if_user_has_guest_access_to_the_list__then_return_the_list(
        dynamodb_lists_table, dynamodb_user_to_lists_table, sample_data):
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.clients.dynamodb import lists_table, user_to_lists_table

    list1 = sample_data['lists'][1]
    lists_table().put_item(Item=list1)
    user_to_lists_table().put_item(Item={
        'user_id': tested_user_id,
        'lists': [list1['id']]
    })

    res = ListsDto.get_all(tested_user_id)
    assert len(res) == 1
    assert ListMappers.map_dto_to_doc(
        res[0]) == ListDocModel.from_db_doc(list1)
Esempio n. 8
0
def test_lists_dto_update__when_user_is_guest__and_updates_only_items__then_update_list(
        dynamodb_lists_table, dynamodb_user_to_lists_table, sample_data):
    from sf_shopping_list.data.db.lists import Lists
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.clients.dynamodb import lists_table

    list1 = sample_data['lists'][1]
    new_list1 = ListModel.parse_obj(list1)

    Lists.save(ListMappers.map_dto_to_doc(new_list1))

    # guest is allowed to change items
    new_list1.items = ['item3', 'item4', 'item5']

    new_list1_res = ListsDto.update(new_list1.id, new_list1, tested_user_id)
    new_list1_saved = lists_table().get_item(Key={'id': new_list1.id})

    assert new_list1_res == new_list1
    assert ListDocModel.from_db_doc(
        new_list1_saved['Item']) == ListMappers.map_dto_to_doc(new_list1)

    # guest is not allowed to modify guests list or name
    new_list1.guests += 'some_other_user_id'
    with pytest.raises(NoAccessError):
        ListsDto.update(new_list1.id, new_list1, tested_user_id)

    new_list1.listName = 'new list name'
    with pytest.raises(NoAccessError):
        ListsDto.update(new_list1.id, new_list1, tested_user_id)
Esempio n. 9
0
def test_lists_dto_update_items__when_user_is_guests__update_the_list(
        dynamodb_lists_table, sample_data):
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.clients.dynamodb import lists_table

    list1 = sample_data['lists'][1]
    lists_table().put_item(Item=list1)
    list_id = list1['id']
    new_items = ['item3', 'item4']

    res = ListsDto.update_items(list_id, new_items, tested_user_id)

    res_saved = lists_table().get_item(Key={'id': list_id})

    assert res == new_items
    assert res_saved['Item']['items'] == new_items
Esempio n. 10
0
def test_lists_dto_add_item__when_user_is_owner__update_the_list(
        dynamodb_lists_table, sample_data):
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.clients.dynamodb import lists_table

    list0 = sample_data['lists'][0]
    lists_table().put_item(Item=list0)
    list_id = list0['id']

    new_item = 'new item'
    res = ListsDto.add_item(list_id, new_item, tested_user_id)

    res_saved = lists_table().get_item(Key={'id': list_id})

    assert new_item in res
    assert new_item in res_saved['Item']['items']
Esempio n. 11
0
 def get(id: str) -> Optional[ListDocModel]:
     res = lists_table().get_item(
         Key={
             'id': id
         }
     )
     if 'Item' in res:
         return ListDocModel.from_db_doc(res['Item'])
     return None
Esempio n. 12
0
def test_lists_dto_add__when_new_list_is_added__then_update_dynamodb__and_return_saved_object(
        dynamodb_lists_table, dynamodb_user_to_lists_table, sample_data):
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.clients.dynamodb import lists_table, user_to_lists_table

    guest_user_id = 'guest1_id'

    # add new list
    new_list = NewList(name='new sample list',
                       items=[
                           'item0',
                           'item1',
                           'item2',
                       ],
                       guests=[guest_user_id])

    with patch('sf_shopping_list.data.dto.lists_dto.datetime',
               spec=datetime) as mock_date:
        mock_date.utcnow.return_value = added_time
        res = ListsDto.create(new_list, tested_user_id)

    # assert returned object has all fields filled correctly
    assert res.id == added_id
    assert res.userId == tested_user_id
    assert res.createdAt == added_time
    assert res.guests == new_list.guests
    assert res.items == new_list.items
    assert res.listName == new_list.name

    # assert returned object has been persisted
    saved_list = lists_table().get_item(Key={'id': added_id})
    assert saved_list['Item'] is not None
    assert ListMappers.map_doc_to_dto(
        ListDocModel.from_db_doc(saved_list['Item'])) == res

    # assert owner user_to_lists entry has been updated with new list
    owner_lists = user_to_lists_table().get_item(
        Key={'user_id': tested_user_id})
    assert owner_lists['Item'] is not None
    assert added_id in owner_lists['Item']['lists']

    # assert guest user_to_lists entry has been updated with new list
    guest_lists = user_to_lists_table().get_item(
        Key={'user_id': guest_user_id})
    assert guest_lists['Item'] is not None
    assert added_id in owner_lists['Item']['lists']
Esempio n. 13
0
    def remove_items(id: str, indices: List[int], user_id: str) -> List[str]:
        with Lists._handle_conditional_check_fail():
            res = lists_table().update_item(
                Key={
                    'id': id
                },
                UpdateExpression='REMOVE ' + ' '.join([f'#i[{i}]' for i in indices]),
                ConditionExpression='#u = :userid Or contains(#g, :userid)',
                ExpressionAttributeNames={
                    '#i': 'items',
                    '#u': 'userId',
                    '#g': 'guests'
                },
                ExpressionAttributeValues={
                    ':userid': user_id
                },
                ReturnValues='UPDATED_NEW'
            )

            if res:
                return list(res['Attributes']['items'])
Esempio n. 14
0
    def update_item(id: str, idx: int, new_item: str, user_id: str) -> List[str]:
        with Lists._handle_conditional_check_fail():
            res = lists_table().update_item(
                Key={
                    'id': id
                },
                UpdateExpression=f'SET #i[{str(idx)}] = :val',
                ConditionExpression='#u = :userid Or contains(#g, :userid)',
                ExpressionAttributeNames={
                    '#i': 'items',
                    '#u': 'userId',
                    '#g': 'guests',
                },
                ExpressionAttributeValues={
                    ':userid': user_id,
                    ':val': new_item
                },
                ReturnValues='UPDATED_NEW'
            )

            if res:
                return list(res['Attributes']['items'])
Esempio n. 15
0
    def append_items(id: str, items: List[str], user_id: str) -> List[str]:
        with Lists._handle_conditional_check_fail():
            res = lists_table().update_item(
                Key={
                    'id': id
                },
                UpdateExpression='SET #i = list_append(#i, :vals)',
                ConditionExpression='#u = :userid Or contains(#g, :userid)',
                ExpressionAttributeNames={
                    '#i': 'items',
                    '#u': 'userId',
                    '#g': 'guests'
                },
                ExpressionAttributeValues={
                    ':vals': items,
                    ':userid': user_id
                },
                ReturnValues='UPDATED_NEW'
            )

            if res:
                return list(res['Attributes']['items'])
Esempio n. 16
0
def test_lists_dto_update__when_user_is_owner__then_update_list(
        dynamodb_lists_table, dynamodb_user_to_lists_table, sample_data):
    from sf_shopping_list.data.dto.lists_dto import ListsDto
    from sf_shopping_list.data.db.lists import Lists
    from sf_shopping_list.data.clients.dynamodb import lists_table
    from sf_shopping_list.data.clients.dynamodb import user_to_lists_table

    list0 = sample_data['lists'][0]
    new_list0 = ListModel.parse_obj(list0)

    Lists.save(ListMappers.map_dto_to_doc(new_list0))

    # owner can change items, guests and listName
    new_list0.items = ['item4', 'item5', 'item6']
    new_list0.guests = {other_user_id}
    new_list0.listName = 'new list name'
    new_list0_res = ListsDto.update(new_list0.id, new_list0, new_list0.userId)
    new_list0_saved = lists_table().get_item(Key={'id': new_list0.id})

    # updated list is returned
    assert new_list0_res == new_list0

    # updated list is saved
    assert ListDocModel.from_db_doc(
        new_list0_saved['Item']) == ListMappers.map_dto_to_doc(new_list0)

    # if guests were added, so their user_to_lists entries were updated
    other_user_lists = user_to_lists_table().get_item(
        Key={'user_id': other_user_id})

    assert new_list0.id in UserToListsDocModel.from_db_doc(
        other_user_lists['Item']).lists

    # try removing guest
    new_list0.guests = set()
    new_list0_res = ListsDto.update(new_list0.id, new_list0, new_list0.userId)
    new_list0_saved = lists_table().get_item(Key={'id': new_list0.id})

    assert new_list0_res == new_list0
    assert ListDocModel.from_db_doc(
        new_list0_saved['Item']) == ListMappers.map_dto_to_doc(new_list0)

    # guests should have their user_to_lists entries updated
    other_user_lists = user_to_lists_table().get_item(
        Key={'user_id': other_user_id})

    assert new_list0.id not in UserToListsDocModel.from_db_doc(
        other_user_lists['Item']).lists

    # try adding guest back
    new_list0.guests = {other_user_id}
    new_list0_res = ListsDto.update(new_list0.id, new_list0, new_list0.userId)
    new_list0_saved = lists_table().get_item(Key={'id': new_list0.id})

    assert new_list0_res == new_list0
    assert ListDocModel.from_db_doc(
        new_list0_saved['Item']) == ListMappers.map_dto_to_doc(new_list0)

    # guests should have their user_to_lists entries updated
    other_user_lists = user_to_lists_table().get_item(
        Key={'user_id': other_user_id})

    # immutable fields changes should be ignored
    original_new_list_0 = new_list0.copy()
    new_list0.id = 'foo'
    new_list0.createdAt = datetime.utcnow()
    new_list0.userId = other_user_id

    new_list0_res = ListsDto.update(original_new_list_0.id, new_list0,
                                    original_new_list_0.userId)
    new_list_0_saved = lists_table().get_item(Key={'id': new_list0.id})

    assert new_list0_res == original_new_list_0
    assert ListDocModel.from_db_doc(
        new_list_0_saved['Item']) == ListMappers.map_dto_to_doc(
            original_new_list_0)

    assert new_list0.id in UserToListsDocModel.from_db_doc(
        other_user_lists['Item']).lists