def test_pro_tier(self, db, project, pro_profile, profile): """ Test able to add more than three collaborators with a private and public app. """ project.is_public = False replace_owner(project, pro_profile) collabs = list(gen_collabs(4)) for collab in collabs: project.assign_role("read", collab.user) assert (get_perms(collab.user, project) == ["read_project"] and project.role(collab.user) == "read") # OK making app private. project.make_private_test() project.is_public = True project.save() for collab in collabs: project.assign_role(None, collab.user) assert project.role(collab.user) == None for collab in collabs: project.assign_role("read", collab.user) assert (get_perms(collab.user, project) == ["read_project"] and project.role(collab.user) == "read") # OK making app private. project.make_private_test()
def test_pro_tier(self, db, tier, get_inputs, meta_param_dict, pro_profile, free_profile): """ Test able to add more than one collaborator with a private and public sim. """ if tier == "free": profile = free_profile else: profile = pro_profile inputs = _submit_inputs("Used-for-testing", get_inputs, meta_param_dict, profile) _, submit_sim = _submit_sim(inputs) sim = submit_sim.submit() sim.status = "SUCCESS" sim.save() collabs = list(gen_collabs(3)) for collab in collabs: sim.assign_role("read", collab.user) assert (get_perms(collab.user, sim) == ["read_simulation"] and sim.role(collab.user) == "read") # OK making sim private. sim.make_private_test() sim.is_public = True sim.save() for collab in collabs: sim.assign_role(None, collab.user) assert sim.role(collab.user) == None for collab in collabs: sim.assign_role("read", collab.user) assert (get_perms(collab.user, sim) == ["read_simulation"] and sim.role(collab.user) == "read") # OK making sim private. sim.make_private_test()
def test_get_private_projects(self, api_client, pro_profile): project = Project.objects.get(title="Used-for-testing") project.is_public = False project.owner = pro_profile replace_owner(project, pro_profile) project.save() # Test private app not included in unauthenticated get resp = api_client.get("/apps/api/v1/") assert resp.status_code == 200 exp = set(proj.title for proj in Project.objects.filter(is_public=True).all()) act = set(proj["title"] for proj in resp.data["results"]) assert exp == act # Test private app not included if user doesn't have write access collab = next(gen_collabs(1)) api_client.force_login(collab.user) resp = api_client.get("/apps/api/v1/") assert resp.status_code == 200 exp = set(proj.title for proj in Project.objects.filter(is_public=True).all()) act = set(proj["title"] for proj in resp.data["results"]) assert exp == act # Test private app included if user has read access api_client.force_login(project.owner.user) resp = api_client.get("/apps/api/v1/") assert resp.status_code == 200 exp = set(proj.title for proj in Project.objects.all()) act = set(proj["title"] for proj in resp.data["results"]) assert exp == act api_client.force_login(collab.user) project.assign_role("read", collab.user) resp = api_client.get("/apps/api/v1/") assert resp.status_code == 200 exp = set(proj.title for proj in Project.objects.all()) act = set(proj["title"] for proj in resp.data["results"]) assert exp == act
def test_list_deployments(self, db, client, api_client, viz_project, mock_deployments_requests_to_cluster): viz_project.sponsor = viz_project.owner viz_project.save() resp = client.get(f"/{viz_project}/viz/") assert resp.status_code == 200 resp = api_client.get(f"/apps/api/v1/deployments/") assert resp.status_code == 403 (collab, ) = gen_collabs(1) api_client.force_login(collab.user) resp = api_client.get(f"/apps/api/v1/deployments/") assert resp.status_code == 200 assert resp.json()["results"] == [] api_client.force_login(viz_project.cluster.service_account.user) resp = api_client.get(f"/apps/api/v1/deployments/") assert resp.status_code == 200 assert (resp.json()["results"] == DeploymentSerializer( Deployment.objects.filter(project=viz_project), many=True).data)
def test_free_tier(self, db, project, free_profile): """ Test private app can not have any collaborators but public is unlimited. """ project.is_public = False project.save() replace_owner(project, free_profile) collabs = list(gen_collabs(3)) # Test cannot add collaborator when app is private. with pytest.raises(PrivateAppException) as excinfo: project.assign_role("read", collabs[0].user) assert excinfo.value.todict() == { "upgrade_to": "pro", "resource": PrivateAppException.resource, "test_name": "make_app_private", "msg": PrivateAppException.msg, } assert (get_perms(collabs[0].user, project) == [] and project.role(collabs[1].user) == None) # Unable for free users to make apps private. with pytest.raises(PrivateAppException): project.make_private_test() # Test no limit on collaborators when app is public. project.is_public = True project.save() for collab in collabs: project.assign_role("read", collab.user) assert (get_perms(collab.user, project) == ["read_project"] and project.role(collab.user) == "read") with pytest.raises(PrivateAppException): project.make_private_test()
def test_private_app_restrictions(self, api_client): post_data = { "title": "New-Model", "oneliner": "oneliner", "description": "**Super** new!", "repo_url": "https://github.com/compute-tooling/compute-studio", "repo_tag": "dev", "cpu": 3, "memory": 9, "listed": True, "is_public": False, } (free_user, ) = gen_collabs(1) api_client.force_login(free_user.user) with mock_sync_projects(): resp = api_client.post("/apps/api/v1/", post_data) assert resp.status_code == 400 data = resp.json() assert "make_app_private" == data["app"]["test_name"] with pytest.raises(Project.DoesNotExist): Project.objects.get(title="New-Model") post_data["is_public"] = True with mock_sync_projects(): resp = api_client.post("/apps/api/v1/", post_data) assert resp.status_code == 200 with mock_sync_projects(): resp = api_client.put( f"/apps/api/v1/{free_user}/New-Model/", {"is_public": False}, ) assert resp.status_code == 400 data = resp.json() assert "make_app_private" == data["app"]["test_name"]
def test_add_authors(db, get_inputs, meta_param_dict, pro_profile): inputs = _submit_inputs("Used-for-testing", get_inputs, meta_param_dict, pro_profile) _, submit_sim = _submit_sim(inputs) sim = submit_sim.submit() sim.status = "SUCCESS" sim.is_public = False sim.save() collab = next(gen_collabs(1)) assert not sim.has_read_access(collab.user) # Create new pending permission object and make sure that read access was # granted appropriately. pp, created = PendingPermission.objects.get_or_create( sim=sim, profile=collab, permission_name="add_author") assert created assert not pp.is_expired() assert sim.has_read_access(collab.user) assert get_perms(collab.user, sim) == ["read_simulation"] sim = Simulation.objects.get(pk=sim.pk) assert sim.pending_permissions.filter(id=pp.id).count() == 1 assert sim.authors.all().count() == 1 and sim.authors.get( pk=pro_profile.pk) pp.add_author() sim = Simulation.objects.get(pk=sim.pk) assert sim.authors.all().count() == 2 and sim.authors.get( pk=collab.pk) == collab assert PendingPermission.objects.filter(id=pp.id).count() == 0
def test_sim_permissions(db, get_inputs, meta_param_dict, pro_profile): collab = next(gen_collabs(1)) inputs = _submit_inputs("Used-for-testing", get_inputs, meta_param_dict, pro_profile) _, submit_sim = _submit_sim(inputs) sim = submit_sim.submit() sim.status = "SUCCESS" sim.is_public = False sim.save() # check permissions for owner and random profile assert get_perms(sim.owner.user, sim) == ["admin_simulation"] assert sim.role(sim.owner.user) == "admin" assert get_perms(collab.user, sim) == [] assert sim.role(collab.user) is None # sim owner has all levels of access assert (sim.is_owner(sim.owner.user) and sim.has_admin_access(sim.owner.user) and sim.has_write_access(sim.owner.user) and sim.has_read_access(sim.owner.user)) # random user has no access assert (not sim.is_owner(collab.user) and not sim.has_admin_access(collab.user) and not sim.has_write_access(collab.user) and not sim.has_read_access(collab.user)) # None has no access and does not cause errors assert (not sim.is_owner(None) and not sim.has_admin_access(None) and not sim.has_write_access(None) and not sim.has_read_access(None)) # test grant/removal of read access. sim.grant_read_permissions(collab.user) assert (get_perms(collab.user, sim) == ["read_simulation"] and sim.role(collab.user) == "read") assert (not sim.is_owner(collab.user) and not sim.has_admin_access(collab.user) and not sim.has_write_access(collab.user) and sim.has_read_access(collab.user)) sim.remove_permissions(collab.user) assert get_perms(collab.user, sim) == [] and sim.role(collab.user) is None assert (not sim.is_owner(collab.user) and not sim.has_admin_access(collab.user) and not sim.has_write_access(collab.user) and not sim.has_read_access(collab.user)) # test grant/remove are idempotent: for _ in range(3): sim.grant_read_permissions(collab.user) assert sim.has_read_access(collab.user) for _ in range(3): sim.remove_permissions(collab.user) assert not sim.has_read_access(collab.user) # test that only one permission is applied at a time. sim.grant_read_permissions(collab.user) assert get_perms(collab.user, sim) == ["read_simulation"] sim.grant_write_permissions(collab.user) assert get_perms(collab.user, sim) == ["write_simulation"] sim.grant_admin_permissions(collab.user) assert get_perms(collab.user, sim) == ["admin_simulation"] sim.is_public = True sim.save() assert sim.has_read_access(pro_profile.user) assert sim.has_read_access(collab.user) assert sim.has_read_access(None) is True # test role sim.is_public = False sim.save() sim.assign_role("admin", collab.user) assert sim.has_admin_access(collab.user) and sim.role( collab.user) == "admin" sim.assign_role("write", collab.user) assert sim.has_write_access(collab.user) and sim.role( collab.user) == "write" sim.assign_role("read", collab.user) assert sim.has_read_access(collab.user) and sim.role(collab.user) == "read" sim.assign_role(None, collab.user) assert not sim.has_read_access(collab.user) and sim.role( collab.user) == None with pytest.raises(ValueError): sim.assign_role("dne", collab.user)
def test_sim_fork(db, get_inputs, meta_param_dict, is_public): (profile, ) = gen_collabs(1, plan="pro") modeler = User.objects.get(username="******").profile inputs = _submit_inputs("Used-for-testing", get_inputs, meta_param_dict, modeler) _, submit_sim = _submit_sim(inputs) sim = submit_sim.submit() sim.inputs.status = "SUCCESS" sim.inputs.save() sim.outputs = "hello world" sim.status = "SUCCESS" sim.is_public = is_public sim.save() next_model_pk = Simulation.objects.next_model_pk(sim.project) newsim = Simulation.objects.fork(sim, profile.user) assert newsim.owner != sim.owner assert newsim.inputs.owner == newsim.owner and newsim.inputs.owner != sim.owner assert newsim.model_pk == next_model_pk assert float(newsim.run_cost) == 0.0 assert newsim.parent_sim == newsim.inputs.parent_sim == sim if not sim.is_public: # make sure each sim's owner has read access and that the # read access for the new sim only applies to the owner # of the new sim and not the owner of the old sim. assert newsim.has_admin_access(newsim.owner.user) assert sim.has_admin_access(sim.owner.user) assert newsim.is_public == False # newsim.save() assert not newsim.has_read_access(sim.owner.user) def objects_eq(obj1, obj2, fields_to_exclude): data1 = model_to_dict(obj1) data2 = model_to_dict(obj2) for field in data1: if field in fields_to_exclude: continue assert (data1[field] == data2[field] ), f"At {field}: {data1[field]} != {data2[field]}" fields_to_exclude = ["id", "owner", "job_id", "parent_sim"] objects_eq(sim.inputs, newsim.inputs, fields_to_exclude) fields_to_exclude += [ "inputs", "run_cost", "model_pk", "creation_date", "authors" ] objects_eq(sim, newsim, fields_to_exclude) sim.status = "PENDING" sim.save() with pytest.raises(ForkObjectException): Simulation.objects.fork(sim, profile.user) sim.inputs.status = "PENDING" sim.inputs.save() with pytest.raises(ForkObjectException): Simulation.objects.fork(sim, profile.user)
def test_put_detail_api( self, client, api_client, test_models, password, visibility_params, ): owner, is_public = visibility_params put_data = { "title": "Used-for-testing", "oneliner": "oneliner", "description": "hello world!", "repo_url": "https://github.com/compute-tooling/compute-studio", "repo_tag": "dev", "cpu": 2, "memory": 6, "lastet_tag": "v2", "is_public": is_public, } project = Project.objects.get(owner=owner, title="Used-for-testing") project.is_public = is_public project.save() # not logged in --> not authorized resp = api_client.put( f"/apps/api/v1/{owner}/Used-for-testing/", data=put_data, content_type="application/json", ) assert resp.status_code == 401 # not the owner --> not authorized client.login(username="******", password="******") resp = client.put( f"/apps/api/v1/{owner}/Used-FOR-testing/", data=put_data, content_type="application/json", ) exp_notauthed_code = 403 if is_public else 404 assert resp.status_code == exp_notauthed_code # logged in and owner --> do update client.force_login(owner.user) with mock_sync_projects(): resp = client.put( f"/apps/api/v1/{owner}/Used-for-testing/", data=put_data, content_type="application/json", ) assert resp.status_code == 200 project = Project.objects.get(title="Used-for-testing", owner=owner) assert project.description == put_data["description"] assert project.status == "running" # test add write_project permission allows update put_data["description"] = "hello world!!" (collab, ) = gen_collabs(1) client.force_login(collab.user) with mock_sync_projects(): resp = client.put( f"/apps/api/v1/{owner}/Used-for-testing/", data=put_data, content_type="application/json", ) # make sure "tester" doesn't have access already. assert resp.status_code == exp_notauthed_code project = Project.objects.get(title="Used-for-testing", owner=owner) project.assign_role("write", collab.user) with mock_sync_projects(): resp = client.put( f"/apps/api/v1/{owner}/Used-for-testing/", data=put_data, content_type="application/json", ) assert resp.status_code == 200 project = Project.objects.get(title="Used-for-testing", owner=owner) assert project.description == put_data["description"]
def test_project_permissions(self, db, project, pro_profile): collab = next(gen_collabs(1)) project.is_public = False replace_owner(project, pro_profile) # check permissions for owner and random profile assert get_perms(project.owner.user, project) == ["admin_project"] assert project.role(project.owner.user) == "admin" assert get_perms(collab.user, project) == [] assert project.role(collab.user) is None # project owner has all levels of access assert (project.is_owner(project.owner.user) and project.has_admin_access(project.owner.user) and project.has_write_access(project.owner.user) and project.has_read_access(project.owner.user)) # random user has no access assert (not project.is_owner(collab.user) and not project.has_admin_access(collab.user) and not project.has_write_access(collab.user) and not project.has_read_access(collab.user)) # None has no access and does not cause errors assert (not project.is_owner(None) and not project.has_admin_access(None) and not project.has_write_access(None) and not project.has_read_access(None)) # test grant/removal of read access. project.grant_read_permissions(collab.user) assert (get_perms(collab.user, project) == ["read_project"] and project.role(collab.user) == "read") assert (not project.is_owner(collab.user) and not project.has_admin_access(collab.user) and not project.has_write_access(collab.user) and project.has_read_access(collab.user)) project.remove_permissions(collab.user) assert (get_perms(collab.user, project) == [] and project.role(collab.user) is None) assert (not project.is_owner(collab.user) and not project.has_admin_access(collab.user) and not project.has_write_access(collab.user) and not project.has_read_access(collab.user)) # test grant/remove are idempotent: for _ in range(3): project.grant_read_permissions(collab.user) assert project.has_read_access(collab.user) for _ in range(3): project.remove_permissions(collab.user) assert not project.has_read_access(collab.user) # test that only one permission is applied at a time. project.grant_read_permissions(collab.user) assert get_perms(collab.user, project) == ["read_project"] project.grant_write_permissions(collab.user) assert get_perms(collab.user, project) == ["write_project"] project.grant_admin_permissions(collab.user) assert get_perms(collab.user, project) == ["admin_project"] project.is_public = True project.save() assert project.has_read_access(pro_profile.user) assert project.has_read_access(collab.user) assert project.has_read_access(None) is True # test role project.is_public = False project.save() project.assign_role("admin", collab.user) assert (project.has_admin_access(collab.user) and project.role(collab.user) == "admin") project.assign_role("write", collab.user) assert (project.has_write_access(collab.user) and project.role(collab.user) == "write") project.assign_role("read", collab.user) assert (project.has_read_access(collab.user) and project.role(collab.user) == "read") project.assign_role(None, collab.user) assert (not project.has_read_access(collab.user) and project.role(collab.user) == None) with pytest.raises(ValueError): project.assign_role("dne", collab.user)