def test_apiview_get_single_config(rf): """Tests retrieving a single object with an m2m field using the API.""" view = UserConfigAPIView.as_view() user0 = UserFactory.create(username='******') user1 = UserFactory.create(username='******') request = create_api_request(rf) response = view(request, id=user0.id) response_data = json.loads(response.content) assert response_data["foo0"] is None assert response_data["foo1"] is None # string config user_config = ObjectConfig(user1) user_config["foo0.bar"] = "foo0.baz" user_config["foo1.bar"] = "foo1.baz" request = create_api_request(rf) response = view(request, id=user1.id) response_data = json.loads(response.content) assert response_data["foo0"] == "foo0.baz" assert response_data["foo1"] == "foo1.baz" # list config user_config["foo0.bar"] = ["foo0.baz"] user_config["foo1.bar"] = ["foo1.baz"] request = create_api_request(rf) response = view(request, id=user1.id) response_data = json.loads(response.content) assert response_data["foo0"] == ["foo0.baz"] assert response_data["foo1"] == ["foo1.baz"]
def test_apiview_get_multi_m2m(rf): """Tests several objects with m2m fields using the API.""" view = UserM2MAPIView.as_view() user0 = UserFactory.create(username='******') user1 = UserFactory.create(username='******') request = create_api_request(rf) response = view(request) response_data = json.loads(response.content) for model in [x for x in response_data["models"] if x['username'] in ['foo0', 'foo1']]: assert model['alt_src_langs'] == [] user0.alt_src_langs.add(LanguageDBFactory(code="alt1")) user0.alt_src_langs.add(LanguageDBFactory(code="alt2")) user1.alt_src_langs.add(LanguageDBFactory(code="alt3")) user1.alt_src_langs.add(LanguageDBFactory(code="alt4")) request = create_api_request(rf) response = view(request) response_data = json.loads(response.content) for model in response_data["models"]: user = User.objects.get(username=model["username"]) if user in [user0, user1]: assert model["alt_src_langs"] assert ( model["alt_src_langs"] == list( str(l) for l in user.alt_src_langs.values_list("pk", flat=True)))
def test_apiview_get_multi_config(rf): """Tests retrieving a single object with an m2m field using the API.""" view = UserConfigAPIView.as_view() user0 = UserFactory.create(username='******') user1 = UserFactory.create(username='******') request = create_api_request(rf) response = view(request) response_data = json.loads(response.content) for model in response_data["models"]: assert model["foo0"] is None assert model["foo1"] is None user_config = ObjectConfig(user0) user_config["foo0.bar"] = "user0.foo0.baz" user_config["foo1.bar"] = "user0.foo1.baz" user_config = ObjectConfig(user1) user_config["foo0.bar"] = "user1.foo0.baz" user_config["foo1.bar"] = "user1.foo1.baz" request = create_api_request(rf) response = view(request) response_data = json.loads(response.content) for model in response_data["models"]: if model["username"] in ["user0", "user1"]: model["foo0"] == "%s.foo0.baz" % model["username"] model["foo1"] == "%s.foo1.baz" % model["username"]
def test_apiview_get_multi_m2m(rf): """Tests several objects with m2m fields using the API.""" view = UserM2MAPIView.as_view() user0 = UserFactory.create(username='******') user1 = UserFactory.create(username='******') request = create_api_request(rf) response = view(request) response_data = json.loads(response.content) for model in [ x for x in response_data["models"] if x['username'] in ['foo0', 'foo1'] ]: assert model['alt_src_langs'] == [] user0.alt_src_langs.add(LanguageDBFactory(code="alt1")) user0.alt_src_langs.add(LanguageDBFactory(code="alt2")) user1.alt_src_langs.add(LanguageDBFactory(code="alt3")) user1.alt_src_langs.add(LanguageDBFactory(code="alt4")) request = create_api_request(rf) response = view(request) response_data = json.loads(response.content) for model in response_data["models"]: user = User.objects.get(username=model["username"]) if user in [user0, user1]: assert model["alt_src_langs"] assert (model["alt_src_langs"] == list( str(l) for l in user.alt_src_langs.values_list("pk", flat=True)))
def test_no_root_view_permissions(po_directory, nobody, default, admin, view, no_permission_sets, no_projects, project_foo, project_bar): """Tests user-accessible projects when there are no permissions set at the root. """ ALL_PROJECTS = [project_foo.code, project_bar.code] foo_user = UserFactory.create(username='******') bar_user = UserFactory.create(username='******') # By setting explicit `view` permissions for `foo_user` in `project_foo`, # only `foo_user` will be able to access that project _require_permission_set(foo_user, project_foo.directory, [view]) assert items_equal(Project.accessible_by_user(admin), ALL_PROJECTS) assert items_equal( Project.accessible_by_user(foo_user), [project_foo.code]) assert items_equal(Project.accessible_by_user(bar_user), []) assert items_equal(Project.accessible_by_user(default), []) assert items_equal(Project.accessible_by_user(nobody), []) # Now let's allow showing `project_bar` to all registered users, but keep # `project_foo` visible only to `foo_user`. _require_permission_set(default, project_bar.directory, [view]) assert items_equal(Project.accessible_by_user(admin), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(foo_user), ALL_PROJECTS) assert items_equal( Project.accessible_by_user(bar_user), [project_bar.code]) assert items_equal(Project.accessible_by_user(default), [project_bar.code]) assert items_equal(Project.accessible_by_user(nobody), [])
def test_apiview_get_multiple(rf, no_extra_users): """Tests retrieving multiple objects using the API.""" view = UserAPIView.as_view() UserFactory.create(username='******') request = create_api_request(rf) response = view(request) response_data = json.loads(response.content) # Response should contain a 1-item list assert response.status_code == 200 assert isinstance(response_data, dict) assert 'count' in response_data assert 'models' in response_data assert len(response_data['models']) == User.objects.count() # Let's add more users UserFactory.create_batch(5) response = view(request) response_data = json.loads(response.content) assert response.status_code == 200 assert isinstance(response_data, dict) assert 'count' in response_data assert 'models' in response_data assert len(response_data['models']) == User.objects.count() # Let's add even more users to test pagination UserFactory.create_batch(5) response = view(request) response_data = json.loads(response.content) # First page is full assert response.status_code == 200 assert isinstance(response_data, dict) assert 'count' in response_data assert 'models' in response_data assert len(response_data['models']) == 10 request = create_api_request(rf, url='/?p=2') response = view(request) response_data = json.loads(response.content) # Second page constains a single user assert response.status_code == 200 assert isinstance(response_data, dict) assert 'count' in response_data assert 'models' in response_data assert len(response_data['models']) == User.objects.count() - 10
def test_duedate_update_project_propagates(): """Tests due date updates at the project level propagate to existing due dates that point to the same resource across languages. """ project_code = 'project0' store_path = '/projects/%s/store0.po' % project_code DueDateFactory.create(pootle_path=store_path, ) project_path = '/projects/%s/' % project_code due_date = DueDateFactory.create(pootle_path=project_path, ) # Update due date with different values other_user = UserFactory.create() other_due_on = aware_datetime(2017, 1, 1, 1, 2, 3) due_date.due_on = other_due_on due_date.modified_by = other_user due_date.save() tp_due_dates = DueDate.objects.for_project_path(project_path).exclude( pootle_path=project_path, ) for tp_due_date in tp_due_dates: assert tp_due_date.due_on == other_due_on assert tp_due_date.modified_by == other_user # Ensure the other due dates haven't been modified store_due_dates = DueDate.objects.for_project_path(store_path).exclude( pootle_path=store_path, ) for store_due_date in store_due_dates: assert store_due_date.due_on != other_due_on assert store_due_date.modified_by != other_user
def test_apiview_check_object_permissions(rf): """Tests permission handlers which trigger a 403.""" class DisallowObjectPermissionClass(object): def has_permission(self, request, view): return True def has_object_permission(self, request, view, obj): return False class AllowObjectPermissionClass(object): def has_permission(self, request, view): return True def has_object_permission(self, request, view, obj): return True user = UserFactory.create(username='******') WriteableUserAPIView.permission_classes = [DisallowObjectPermissionClass] view = WriteableUserAPIView.as_view() request = create_api_request(rf, method='delete') response = view(request, id=user.id) response_data = json.loads(response.content) assert response.status_code == 403 assert 'msg' in response_data assert response_data['msg'] == 'Permission denied.' WriteableUserAPIView.permission_classes = [AllowObjectPermissionClass] view = WriteableUserAPIView.as_view() request = create_api_request(rf, method='delete') response = view(request, id=user.id) response_data = json.loads(response.content) assert response.status_code == 200
def test_no_root_hide_permissions(nobody, default, admin, hide, view, no_projects, no_permission_sets, project_foo, project_bar, root): """Tests user-accessible projects when there are no `hide` permissions set at the root. """ ALL_PROJECTS = [project_foo.code, project_bar.code] foo_user = UserFactory.create(username='******') bar_user = UserFactory.create(username='******') # By default everyone has access to projects _require_permission_set(default, root, [view]) _require_permission_set(nobody, root, [view]) # At the same time, `project_foo` is inaccessible registered users... _require_permission_set(default, project_foo.directory, negative_permissions=[hide]) assert items_equal(Project.accessible_by_user(admin), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(default), [project_bar.code]) assert items_equal(Project.accessible_by_user(nobody), [project_bar.code]) assert items_equal(Project.accessible_by_user(foo_user), [project_bar.code]) assert items_equal(Project.accessible_by_user(bar_user), [project_bar.code]) # ...and anonymous users as well _require_permission_set(nobody, project_foo.directory, negative_permissions=[hide]) assert items_equal(Project.accessible_by_user(nobody), [project_bar.code]) # Let's make `project_foo` accessible for `foo_user` _require_permission_set(foo_user, project_foo.directory, [view]) assert items_equal(Project.accessible_by_user(foo_user), ALL_PROJECTS) # `project_bar` is now inaccessible for anonymous users _require_permission_set(nobody, project_bar.directory, negative_permissions=[hide]) assert items_equal(Project.accessible_by_user(nobody), [])
def test_no_root_hide_permissions(po_directory, nobody, default, admin, hide, view, no_projects, no_permission_sets, project_foo, project_bar, root): """Tests user-accessible projects when there are no `hide` permissions set at the root. """ ALL_PROJECTS = [project_foo.code, project_bar.code] foo_user = UserFactory.create(username='******') bar_user = UserFactory.create(username='******') # By default everyone has access to projects _require_permission_set(default, root, [view]) _require_permission_set(nobody, root, [view]) # At the same time, `project_foo` is inaccessible registered users... _require_permission_set(default, project_foo.directory, negative_permissions=[hide]) assert items_equal(Project.accessible_by_user(admin), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(default), [project_bar.code]) assert items_equal(Project.accessible_by_user(nobody), [project_bar.code]) assert items_equal( Project.accessible_by_user(foo_user), [project_bar.code]) assert items_equal( Project.accessible_by_user(bar_user), [project_bar.code]) # ...and anonymous users as well _require_permission_set(nobody, project_foo.directory, negative_permissions=[hide]) assert items_equal(Project.accessible_by_user(nobody), [project_bar.code]) # Let's make `project_foo` accessible for `foo_user` _require_permission_set(foo_user, project_foo.directory, [view]) assert items_equal(Project.accessible_by_user(foo_user), ALL_PROJECTS) # `project_bar` is now inaccessible for anonymous users _require_permission_set(nobody, project_bar.directory, negative_permissions=[hide]) assert items_equal(Project.accessible_by_user(nobody), [])
def test_apiview_put(rf): """Tests updating an object using the API.""" view = WriteableUserAPIView.as_view() user = UserFactory.create(username='******') # Malformed request, only JSON-encoded data is understood request = create_api_request(rf, 'put') response = view(request, id=user.id) response_data = json.loads(response.content) assert response.status_code == 400 assert response_data['msg'] == 'Invalid JSON data' # Update a field's data new_username = '******' update_data = { 'username': new_username, } request = create_api_request(rf, 'put', data=update_data) # Requesting unknown resources is a 404 with pytest.raises(Http404): view(request, id='11') # All fields must be submitted response = view(request, id=user.id) response_data = json.loads(response.content) assert response.status_code == 400 assert 'errors' in response_data # Specify missing fields update_data.update({ 'email': user.email, }) request = create_api_request(rf, 'put', data=update_data) response = view(request, id=user.id) response_data = json.loads(response.content) # Now all is ok assert response.status_code == 200 assert response_data['username'] == new_username # Email shouldn't have changed assert response_data['email'] == user.email # View with a custom form update_data.update({ 'password': '******', }) view = WriteableUserSettingsAPIView.as_view() request = create_api_request(rf, 'put', data=update_data) response = view(request, id=user.id) response_data = json.loads(response.content) assert response.status_code == 200 assert 'password' not in response_data
def test_root_hide_permissions(po_directory, nobody, default, admin, hide, view, no_permission_sets, no_projects, project_foo, project_bar, root): """Tests user-accessible projects when there are `hide` permissions set at the root. """ ALL_PROJECTS = [project_foo.code, project_bar.code] foo_user = UserFactory.create(username='******') bar_user = UserFactory.create(username='******') # By default all projects are not accessible _require_permission_set(default, root, negative_permissions=[hide]) _require_permission_set(nobody, root, negative_permissions=[hide]) assert items_equal(Project.accessible_by_user(admin), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(default), []) assert items_equal(Project.accessible_by_user(nobody), []) assert items_equal(Project.accessible_by_user(foo_user), []) assert items_equal(Project.accessible_by_user(bar_user), []) # Now let's make `project_foo` accessible to `foo_user`. _require_permission_set(foo_user, project_foo.directory, [view]) assert items_equal(Project.accessible_by_user(admin), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(default), []) assert items_equal(Project.accessible_by_user(nobody), []) assert items_equal( Project.accessible_by_user(foo_user), [project_foo.code]) assert items_equal(Project.accessible_by_user(bar_user), []) # Making projects accessible for anonymous users should open the door for # everyone _require_permission_set(nobody, root, [view]) assert items_equal(Project.accessible_by_user(admin), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(default), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(nobody), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(foo_user), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(bar_user), ALL_PROJECTS)
def test_root_view_permissions(po_directory, nobody, default, admin, view, no_projects, no_permission_sets, project_foo, project_bar, root): """Tests user-accessible projects with view permissions at the root.""" ALL_PROJECTS = [project_foo.code, project_bar.code] foo_user = UserFactory.create(username='******') bar_user = UserFactory.create(username='******') # We'll only give `bar_user` access to all projects server-wide _require_permission_set(bar_user, root, [view]) assert items_equal(Project.accessible_by_user(admin), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(bar_user), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(foo_user), []) assert items_equal(Project.accessible_by_user(default), []) assert items_equal(Project.accessible_by_user(nobody), []) # Now we'll also allow `foo_user` access `project_foo` _require_permission_set(foo_user, project_foo.directory, [view]) assert items_equal( Project.accessible_by_user(foo_user), [project_foo.code]) # Let's change server-wide defaults: all registered users have access to # all projects. `foo_user`, albeit having explicit access for # `project_foo`, will be able to access any project because they fall back # and extend with the defaults. _require_permission_set(default, root, [view]) assert items_equal(Project.accessible_by_user(admin), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(foo_user), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(bar_user), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(default), ALL_PROJECTS) assert items_equal(Project.accessible_by_user(nobody), []) # Let's give anonymous users access to all projects too _require_permission_set(nobody, root, [view]) assert items_equal(Project.accessible_by_user(nobody), ALL_PROJECTS)
def test_apiview_search(rf): """Tests filtering through a search query.""" # Note that `UserAPIView` is configured to search in all defined fields, # which are `username` and `full_name` view = UserAPIView.as_view() # Let's create some users to search for UserFactory.create(username='******', full_name='Foo Bar') UserFactory.create(username='******', full_name='Foo Bar') UserFactory.create(username='******', full_name='Foo Bar') # `q=bar` should match 3 users (full names match) request = create_api_request(rf, url='/?q=bar') response = view(request) response_data = json.loads(response.content) assert response.status_code == 200 assert len(response_data['models']) == 3 # `q=baz` should match 1 user request = create_api_request(rf, url='/?q=baz') response = view(request) response_data = json.loads(response.content) assert response.status_code == 200 assert len(response_data['models']) == 1 # Searches are case insensitive; `q=BaZ` should match 1 user request = create_api_request(rf, url='/?q=BaZ') response = view(request) response_data = json.loads(response.content) assert response.status_code == 200 assert len(response_data['models']) == 1
def test_apiview_put(rf): """Tests updating an object using the API.""" view = WriteableUserAPIView.as_view() user = UserFactory.create(username="******") # Malformed request, only JSON-encoded data is understood request = create_api_request(rf, "put") response = view(request, id=user.id) response_data = json.loads(response.content) assert response.status_code == 400 assert response_data["msg"] == "Invalid JSON data" # Update a field's data new_username = "******" update_data = {"username": new_username} request = create_api_request(rf, "put", data=update_data) # Requesting unknown resources is a 404 with pytest.raises(Http404): view(request, id="11") # All fields must be submitted response = view(request, id=user.id) response_data = json.loads(response.content) assert response.status_code == 400 assert "errors" in response_data # Specify missing fields update_data.update({"email": user.email}) request = create_api_request(rf, "put", data=update_data) response = view(request, id=user.id) response_data = json.loads(response.content) # Now all is ok assert response.status_code == 200 assert response_data["username"] == new_username # Email shouldn't have changed assert response_data["email"] == user.email # View with a custom form update_data.update({"password": "******"}) view = WriteableUserSettingsAPIView.as_view() request = create_api_request(rf, "put", data=update_data) response = view(request, id=user.id) response_data = json.loads(response.content) assert response.status_code == 200 assert "password" not in response_data
def test_apiview_get_single_m2m(rf): """Tests retrieving a single object with an m2m field using the API.""" view = UserM2MAPIView.as_view() user = UserFactory.create(username="******") request = create_api_request(rf) response = view(request, id=user.id) response_data = json.loads(response.content) assert response_data["alt_src_langs"] == [] user.alt_src_langs.add(LanguageDBFactory(code="alt1")) user.alt_src_langs.add(LanguageDBFactory(code="alt2")) request = create_api_request(rf) response = view(request, id=user.id) response_data = json.loads(response.content) assert response_data["alt_src_langs"] assert response_data["alt_src_langs"] == list(str(l) for l in user.alt_src_langs.values_list("pk", flat=True))
def test_apiview_get_single_m2m(rf): """Tests retrieving a single object with an m2m field using the API.""" view = UserM2MAPIView.as_view() user = UserFactory.create(username='******') request = create_api_request(rf) response = view(request, id=user.id) response_data = json.loads(response.content) assert response_data["alt_src_langs"] == [] user.alt_src_langs.add(LanguageDBFactory(code="alt1")) user.alt_src_langs.add(LanguageDBFactory(code="alt2")) request = create_api_request(rf) response = view(request, id=user.id) response_data = json.loads(response.content) assert response_data["alt_src_langs"] assert (response_data["alt_src_langs"] == list( str(l) for l in user.alt_src_langs.values_list("pk", flat=True)))
def test_apiview_get_single(rf): """Tests retrieving a single object using the API.""" view = UserAPIView.as_view() user = UserFactory.create(username='******') request = create_api_request(rf) response = view(request, id=user.id) # This should have been a valid request... assert response.status_code == 200 # ...and JSON-encoded, so should properly parse it response_data = json.loads(response.content) assert isinstance(response_data, dict) assert response_data['username'] == 'foo' assert 'email' not in response_data # Non-existent IDs should return 404 with pytest.raises(Http404): view(request, id='777')
def test_apiview_delete(rf): """Tests deleting an object using the API.""" view = UserAPIView.as_view() user = UserFactory.create(username='******') # Delete is not supported for collections request = create_api_request(rf, 'delete') response = view(request) assert response.status_code == 405 assert User.objects.filter(id=user.id).count() == 1 # But it is supported for single items (specified by id): response = view(request, id=user.id) assert response.status_code == 200 assert User.objects.filter(id=user.id).count() == 0 # Should raise 404 if we try to access a deleted resource again: with pytest.raises(Http404): view(request, id=user.id)
def test_pending_agreements(): """Tests proper user pending agreements are returned.""" foo_user = UserFactory.create(username='******') privacy_policy = LegalPageFactory.create( active=True, modified_on=aware_datetime(2014, 01, 01), ) # `foo_user` hasn't agreed the privacy policy yet pending = list(LegalPage.objects.pending_user_agreement(foo_user)) assert len(pending) == 1 assert privacy_policy in pending # `foo_user` agreed the privacy policy AgreementFactory.create( user=foo_user, document=privacy_policy, agreed_on=aware_datetime(2014, 02, 02), ) pending = list(LegalPage.objects.pending_user_agreement(foo_user)) assert len(pending) == 0 # Let's add a new ToS tos = LegalPageFactory.create( active=True, modified_on=aware_datetime(2015, 01, 01), ) pending = list(LegalPage.objects.pending_user_agreement(foo_user)) assert len(pending) == 1 assert tos in pending # `foo_user` also accepted the ToS AgreementFactory.create( user=foo_user, document=tos, agreed_on=aware_datetime(2015, 02, 02), ) pending = list(LegalPage.objects.pending_user_agreement(foo_user)) assert len(pending) == 0 # The ToS were modified, `foo_user` must agree it tos.modified_on = aware_datetime(2015, 03, 03) tos.save() pending = list(LegalPage.objects.pending_user_agreement(foo_user)) assert len(pending) == 1 assert tos in pending # Same with the privacy policy privacy_policy.modified_on = aware_datetime(2015, 04, 04) privacy_policy.save() pending = list(LegalPage.objects.pending_user_agreement(foo_user)) assert len(pending) == 2 assert privacy_policy in pending assert tos in pending # Let's disable the ToS tos.active = False tos.save() pending = list(LegalPage.objects.pending_user_agreement(foo_user)) assert len(pending) == 1 assert privacy_policy in pending