def test_get_total_users_returns_number_of_users(self): expected_number_of_users = 3 UserFactory.create_batch(expected_number_of_users) total_users = cached_users.get_total_users() assert total_users == expected_number_of_users, total_users
def test_limits_query(self): """Test API GET limits works""" owner = UserFactory.create() projects = ProjectFactory.create_batch(30, owner=owner) for project in projects: task = TaskFactory.create(project=project) TaskRunFactory.create(task=task) res = self.app.get('/api/project') data = json.loads(res.data) assert len(data) == 20, len(data) res = self.app.get('/api/project?limit=10') data = json.loads(res.data) assert len(data) == 10, len(data) # DEPRECATED res = self.app.get('/api/project?limit=10&offset=10') data = json.loads(res.data) assert len(data) == 10, len(data) assert data[0].get('name') == projects[10].name, data[0] # Keyset pagination url = '/api/project?limit=10&last_id=%s' % projects[9].id res = self.app.get(url) data = json.loads(res.data) assert len(data) == 10, len(data) assert data[0].get('name') == projects[10].name, data[0] res = self.app.get('/api/task') data = json.loads(res.data) assert len(data) == 20, len(data) res = self.app.get('/api/taskrun') data = json.loads(res.data) assert len(data) == 20, len(data) UserFactory.create_batch(30) res = self.app.get('/api/user') data = json.loads(res.data) assert len(data) == 20, len(data) res = self.app.get('/api/user?limit=10') data = json.loads(res.data) assert len(data) == 10, len(data) # DEPRECATED res = self.app.get('/api/user?limit=10&offset=10') data = json.loads(res.data) assert len(data) == 10, len(data) assert data[0].get('name') == 'user11', data res = self.app.get('/api/user?limit=10&last_id=10') data = json.loads(res.data) assert len(data) == 10, len(data) assert data[0].get('name') == 'user11', data
def test_filter_by_one_condition(self): """Test filter_by returns a list of users that meet the filtering condition""" UserFactory.create_batch(3, locale='es') should_be_missing = UserFactory.create(locale='fr') retrieved_users = self.user_repo.filter_by(locale='es') assert len(retrieved_users) == 3, retrieved_users assert should_be_missing not in retrieved_users, retrieved_users
def test_filter_by_multiple_conditions(self): """Test filter_by supports multiple-condition queries""" UserFactory.create_batch(2, locale='es', privacy_mode=True) user = UserFactory.create(locale='es', privacy_mode=False) retrieved_users = self.user_repo.filter_by(locale='es', privacy_mode=False) assert len(retrieved_users) == 1, retrieved_users assert user in retrieved_users, retrieved_users
def test_filter_by_limit_offset(self): """Test that filter_by supports limit and offset options""" UserFactory.create_batch(4) all_users = self.user_repo.filter_by() first_two = self.user_repo.filter_by(limit=2) last_two = self.user_repo.filter_by(limit=2, offset=2) assert len(first_two) == 2, first_two assert len(last_two) == 2, last_two assert first_two == all_users[:2] assert last_two == all_users[2:]
def test_get_query_with_api_key_and_all(self): """ Test API GET query with an API-KEY requesting all results""" users = UserFactory.create_batch(3) project = ProjectFactory.create(owner=users[0], info={'total': 150}) task = TaskFactory.create(project=project, info={'url': 'my url'}) taskrun = TaskRunFactory.create(task=task, user=users[0], info={'answer': 'annakarenina'}) for endpoint in self.endpoints: url = '/api/' + endpoint + '?api_key=' + users[1].api_key + '&all=1' res = self.app.get(url) data = json.loads(res.data) if endpoint == 'project': assert len(data) == 1, data project = data[0] assert project['info']['total'] == 150, data assert res.mimetype == 'application/json', res if endpoint == 'task': assert len(data) == 1, data task = data[0] assert task['info']['url'] == 'my url', data assert res.mimetype == 'application/json', res if endpoint == 'taskrun': assert len(data) == 1, data taskrun = data[0] assert taskrun['info']['answer'] == 'annakarenina', data assert res.mimetype == 'application/json', res if endpoint == 'user': assert len(data) == 3, data user = data[0] assert user['name'] == 'user1', data assert res.mimetype == 'application/json', res
def setUpClass(self): """ Create user locations if does not exist already """ if not UserLocation.objects.all(): fnames, lnames = self.create_names_list() # Iterate 50 times to create batch profiles of about 10000 users for iteration in range(50): fname = (random.choice(fnames)).lower() lname = (random.choice(lnames)).lower() sname = fname[0] + lname users = UserFactory.create_batch(200, first_name=fname, last_name=lname, short_name=sname) for user in users: # Create a batch of 200 userlocations corresponding # to each user new_lat,new_lng = self.calc_rand_loctn( 40.7033127, -73.979681, 5) UserLocationFactory.create( lat=new_lat, lng=new_lng, user=user)
def test_05_app_stats_index(self): '''Test PRIVACY project stats privacy is respected''' # As Anonymou user admin, user, owner = UserFactory.create_batch(3) task = TaskFactory.create(n_answers=3) TaskRunFactory.create_batch(3, task=task) url = '/project/%s/stats' % task.project.short_name update_stats(task.project.id) res = self.app.get(url, follow_redirects=True) dom = BeautifulSoup(res.data) err_msg = 'Project Stats page should not be shown to anonymous users' assert dom.find(id='enforce_privacy') is not None, res.data # As Authenticated user but NOT ADMIN res = self.app.get(url + '?api_key=%s' % user.api_key, follow_redirects=True) dom = BeautifulSoup(res.data) err_msg = 'Project Stats page should not be shown to authenticated users' assert dom.find(id='enforce_privacy') is not None, err_msg self.signout # As Authenticated user but ADMIN res = self.app.get(url + '?api_key=%s' % admin.api_key, follow_redirects=True) dom = BeautifulSoup(res.data) err_msg = 'Project Stats page should be shown to admin users' assert dom.find(id='enforce_privacy') is None, err_msg self.signout()
def test_delete_helpingmaterial(self, mock_delete): """Test API HelpingMaterialpost delete post (DEL).""" mock_delete.return_value = True admin, owner, user = UserFactory.create_batch(3) project = ProjectFactory.create(owner=owner) file_info = {'file_name': 'name.jpg', 'container': 'user_3'} helpingmaterial = HelpingMaterialFactory.create(project_id=project.id, info=file_info) helpingmaterial2 = HelpingMaterialFactory.create(project_id=project.id) # As anon url = '/api/helpingmaterial/%s' % helpingmaterial.id res = self.app.delete(url) assert res.status_code == 401, res.status_code # As user url = '/api/helpingmaterial/%s?api_key=%s' % (helpingmaterial.id, user.api_key) res = self.app.delete(url) assert res.status_code == 403, res.status_code # As owner url = '/api/helpingmaterial/%s?api_key=%s' % (helpingmaterial.id, owner.api_key) res = self.app.delete(url) assert res.status_code == 204, res.status_code mock_delete.assert_called_with(file_info['file_name'], file_info['container']) # As admin url = '/api/helpingmaterial/%s?api_key=%s' % (helpingmaterial2.id, admin.api_key) res = self.app.delete(url) assert res.status_code == 204, res.status_code
def test_get_users_page_only_returns_users_with_contributions(self): users = UserFactory.create_batch(2) TaskRunFactory.create(user=users[0]) users_with_contrib = cached_users.get_users_page(1) assert len(users_with_contrib) == 1, users_with_contrib
def test_owner_user_cannot_read_project_auditlogs(self): """Test owner users cannot read auditlogs of a specific project""" owner = UserFactory.create_batch(2)[1] project = ProjectFactory.create(owner=owner) assert_raises(Forbidden, ensure_authorized_to, 'read', Auditlog, project_id=project.id)
def test_owner_user_cannot_read_project_webhooks(self): """Test owner users can read webhooks of a specific project""" owner = UserFactory.create_batch(2)[1] project = ProjectFactory.create(owner=owner) assert_not_raises(Exception, ensure_authorized_to, 'read', Webhook, project_id=project.id)
def test_announcement_post(self): """Test API Announcement creation.""" admin, user = UserFactory.create_batch(2) payload = dict(title='hello', body='world') # As anon url = '/api/announcement' res = self.app.post(url, data=json.dumps(payload)) data = json.loads(res.data) assert res.status_code == 401, data assert data['status_code'] == 401, data # As a user url = '/api/announcement?api_key=%s' % user.api_key res = self.app.post(url, data=json.dumps(payload)) data = json.loads(res.data) assert res.status_code == 403, data assert data['status_code'] == 403, data # As admin url = '/api/announcement?api_key=%s' % admin.api_key res = self.app.post(url, data=json.dumps(payload)) data = json.loads(res.data) assert res.status_code == 200, data assert data['title'] == 'hello', data assert data['body'] == 'world', data
def test_anon_week(self): """Test JOB leaderboard returns anon active week runs.""" users = UserFactory.create_batch(20) for user in users: TaskRunFactory.create(user=user) leaderboard() top_users = get_leaderboard() assert len(top_users) == 20, len(top_users)
def test_pro_user_cannot_read_project_auditlogs(self): """Test pro users cannot read auditlogs from a non-owned project""" users = UserFactory.create_batch(2, pro=True) project = ProjectFactory.create(owner=users[0]) assert self.mock_pro.id != project.owner_id assert_raises(Forbidden, ensure_authorized_to, 'read', Auditlog, project_id=project.id)
def test_admin_user_can_read_project_webhooks(self): """Test admin users can read webhooks from a project""" owner = UserFactory.create_batch(2)[1] project = ProjectFactory.create(owner=owner) assert self.mock_admin.id != project.owner_id assert_not_raises(Exception, ensure_authorized_to, 'read', Webhook, project_id=project.id)
def test_pro_user_can_read_project_auditlogs(self): """Test pro users cannot read auditlogs from an owned project""" owner = UserFactory.create_batch(2, pro=True)[1] project = ProjectFactory.create(owner=owner) assert self.mock_pro.id == project.owner_id assert_not_raises(Exception, ensure_authorized_to, 'read', Auditlog, project_id=project.id)
def test_get_query_with_api_key_context(self): """ Test API GET query with an API-KEY requesting only APIKEY results.""" users = UserFactory.create_batch(4) project_oc = ProjectFactory.create(owner=users[0], info={'total': 150}) projects = ProjectFactory.create_batch(3, owner=users[1]) task_oc = TaskFactory.create(project=project_oc, info={'url': 'my url'}) taskrun_oc = TaskRunFactory.create(task=task_oc, user=users[0], info={'answer': 'annakarenina'}) for p in projects: print p.owner_id task_tmp = TaskFactory.create(project=p) TaskRunFactory.create(task=task_tmp) # For project owner with associated data for endpoint in self.endpoints: url = '/api/' + endpoint + '?api_key=' + users[0].api_key res = self.app.get(url) data = json.loads(res.data) if endpoint == 'project': assert len(data) == 1, data project = data[0] assert project['owner_id'] == users[0].id, project['owner_id'] assert project['info']['total'] == 150, data assert res.mimetype == 'application/json', res if endpoint == 'task': assert len(data) == 1, data task = data[0] assert task['project_id'] == project_oc.id, task assert task['info']['url'] == 'my url', data assert res.mimetype == 'application/json', res if endpoint == 'taskrun': assert len(data) == 1, data taskrun = data[0] assert taskrun['project_id'] == project_oc.id, taskrun assert taskrun['info']['answer'] == 'annakarenina', data assert res.mimetype == 'application/json', res # For authenticated with non-associated data for endpoint in self.endpoints: url = '/api/' + endpoint + '?api_key=' + users[3].api_key res = self.app.get(url) data = json.loads(res.data) if endpoint == 'project': assert len(data) == 0, data assert res.mimetype == 'application/json', res if endpoint == 'task': assert len(data) == 0, data assert res.mimetype == 'application/json', res if endpoint == 'taskrun': assert len(data) == 0, data assert res.mimetype == 'application/json', res
def test_admin_user_can_read_auditlog(self): """Test admin users can read an auditlog""" owner = UserFactory.create_batch(2)[1] project = ProjectFactory.create(owner=owner) log = AuditlogFactory.create(project_id=project.id) assert self.mock_admin.id != project.owner_id assert_not_raises(Exception, ensure_authorized_to, 'read', log)
def test_owner_read_blogposts_for_given_draft_project(self): """Test authenticated user can read blogposts of a given draft project if is the project owner""" owner = UserFactory.create_batch(2)[1] project = ProjectFactory.create(owner=owner, published=False) assert self.mock_authenticated.id == project.owner.id assert_not_raises(Exception, ensure_authorized_to, 'read', Blogpost, project_id=project.id)
def test_owner_delete_blogpost(self): """Test authenticated user can delete a blogpost if is the post owner""" owner = UserFactory.create_batch(2)[1] project = ProjectFactory.create() blogpost = BlogpostFactory.create(project=project, owner=owner) assert self.mock_authenticated.id == blogpost.owner.id assert_not_raises(Exception, ensure_authorized_to, 'delete', blogpost)
def test_get_users_page_supports_pagination(self): users = UserFactory.create_batch(3) for user in users: TaskRunFactory.create(user=user) paginated_users = cached_users.get_users_page(page=2, per_page=1) assert len(paginated_users) == 1, paginated_users assert paginated_users[0]['id'] == users[1].id
def test_non_owner_authenticated_user_create_blogpost_for_given_project(self): """Test authenticated user cannot create blogposts for a given project if is not the project owner, even if is admin""" owner = UserFactory.create_batch(2)[1] project = ProjectFactory.create(owner=owner) assert self.mock_admin.id != project.owner.id assert_raises(Forbidden, ensure_authorized_to, 'create', Blogpost, project_id=project.id)
def test_non_owner_authenticated_user_create_blogpost_for_given_app(self): """Test authenticated user cannot create blogposts for a given project if is not the project owner, even if is admin""" owner = UserFactory.create_batch(2)[1] app = AppFactory.create(owner=owner) assert self.mock_admin.id != app.owner.id assert_raises(Forbidden, getattr(require, 'blogpost').create, app_id=app.id)
def test_owner_create_given_blogpost(self): """Test authenticated user can create a given blogpost if is project owner""" owner = UserFactory.create_batch(2)[1] app = AppFactory.create(owner=owner) blogpost = BlogpostFactory.build(app=app, owner=owner) assert self.mock_authenticated.id == app.owner_id assert_not_raises(Exception, getattr(require, 'blogpost').create, blogpost)
def test_owner_delete_blogpost(self): """Test authenticated user can delete a blogpost if is the post owner""" owner = UserFactory.create_batch(2)[1] app = AppFactory.create() blogpost = BlogpostFactory.create(app=app, owner=owner) assert self.mock_authenticated.id == blogpost.owner.id assert_not_raises(Exception, getattr(require, 'blogpost').delete, blogpost)
def test_owner_read_blogposts_for_given_hidden_app(self): """Test authenticated user can read blogposts of a given hidden project if is the project owner""" owner = UserFactory.create_batch(2)[1] app = AppFactory.create(owner=owner, hidden=1) assert self.mock_authenticated.id == app.owner.id assert_not_raises(Exception, getattr(require, 'blogpost').read, app_id=app.id)
def test_owner_create_blogpost_for_given_app(self): """Test authenticated user can create blogposts for a given project if is project owner""" owner = UserFactory.create_batch(2)[1] app = AppFactory.create(owner=owner) assert self.mock_authenticated.id == app.owner.id assert_not_raises(Exception, getattr(require, 'blogpost').create, app_id=app.id)
def test_owner_create_given_blogpost(self): """Test authenticated user can create a given blogpost if is project owner""" owner = UserFactory.create_batch(2)[1] project = ProjectFactory.create(owner=owner) blogpost = BlogpostFactory.build(project=project, owner=owner) assert self.mock_authenticated.id == project.owner_id assert_not_raises(Exception, ensure_authorized_to, 'create', blogpost)
def test_transfer_auth_not_owner_get(self): """Test transfer ownership page is forbidden for not owner.""" admin, owner, user = UserFactory.create_batch(3) project = ProjectFactory.create(owner=owner) url = '/project/%s/transferownership?api_key=%s' % (project.short_name, user.api_key) res = self.app_get_json(url, follow_redirects=True) data = json.loads(res.data) assert data['code'] == 403, data
def test_transfer_auth_admin_post(self): """Test transfer ownership page post is ok for admin.""" admin, owner, user = UserFactory.create_batch(3) project = ProjectFactory.create(owner=owner) url = '/project/%s/transferownership?api_key=%s' % (project.short_name, admin.api_key) assert project.owner_id == owner.id payload = dict(email_addr=user.email_addr) res = self.app_post_json(url, data=payload, follow_redirects=True) data = json.loads(res.data) assert data['next'] is not None, data err_msg = "The project owner id should be different" assert project.owner_id == user.id, err_msg
def test_announcement_put_file(self): """Test API Announcement file upload update.""" admin, user = UserFactory.create_batch(2) announcement = AnnouncementFactory.create() img = (io.BytesIO(b'test'), 'test_file.jpg') payload = dict(file=img) # As anon url = '/api/announcement/%s' % announcement.id res = self.app.put(url, data=payload, content_type="multipart/form-data") data = json.loads(res.data) assert res.status_code == 401, data assert data['status_code'] == 401, data # As a user img = (io.BytesIO(b'test'), 'test_file.jpg') payload = dict(file=img) url = '/api/announcement/%s?api_key=%s' % (announcement.id, user.api_key) res = self.app.put(url, data=payload, content_type="multipart/form-data") data = json.loads(res.data) assert res.status_code == 403, data assert data['status_code'] == 403, data # As admin img = (io.BytesIO(b'test'), 'test_file.jpg') payload = dict(file=img) url = '/api/announcement/%s?api_key=%s' % (announcement.id, admin.api_key) res = self.app.put(url, data=payload, content_type="multipart/form-data") data = json.loads(res.data) assert res.status_code == 200, data container = "user_%s" % admin.id assert data['info']['container'] == container, data assert data['info']['file_name'] == 'test_file.jpg', data assert 'test_file.jpg' in data['media_url'], data
def test_proxy_s3_error(self, create_connection): admin, owner = UserFactory.create_batch(2) project = ProjectFactory.create(owner=owner) url = '/fileproxy/encrypted/s3/test/%s/file.pdf' % project.id task = TaskFactory.create(project=project, info={'url': url}) signature = signer.dumps({'task_id': task.id}) req_url = '%s?api_key=%s&task-signature=%s' % (url, admin.api_key, signature) key = self.get_key(create_connection) key.get_contents_as_string.side_effect = S3ResponseError( 403, 'Forbidden') res = self.app.get(req_url, follow_redirects=True) assert res.status_code == 500, res.status_code
def test_get_top5_users_24_hours_returns_best_5_users_only(self): users = UserFactory.create_batch(5) i = 5 for user in users: TaskRunFactory.create_batch(i, user=user) i -= 1 worst_user = UserFactory.create() top5 = stats.get_top5_users_24_hours() top5_ids = [top['id'] for top in top5] assert len(top5) == 5 assert worst_user.id not in top5_ids for i in range(len(top5)): assert users[i].id == top5_ids[i]
def test_password_not_required_for_owner_to_see_project(self, mock_user): """Test when the owner wants to visit a password protected project is able to do it""" owner = UserFactory.create_batch(2)[1] configure_mock_current_user_from(owner, mock_user) assert owner.admin is False app = AppFactory.create(owner=owner) assert app.owner.id == owner.id TaskFactory.create(app=app) app.set_password('mysecret') project_repo.update(app) for endpoint in self.endpoints_requiring_password: res = self.app.get('/app/%s%s' % (app.short_name, endpoint), follow_redirects=True) assert 'Enter the password to contribute' not in res.data, endpoint
def test_transfer_auth_owner_post_wrong_email(self): """Test transfer ownership page post is ok for wrong email.""" admin, owner, user = UserFactory.create_batch(3) make_subadmin(owner) project = ProjectFactory.create(owner=owner) url = '/project/%s/transferownership?api_key=%s' % (project.short_name, owner.api_key) assert project.owner_id == owner.id payload = dict(email_addr="*****@*****.**") res = self.app_post_json(url, data=payload, follow_redirects=True) data = json.loads(res.data) assert data['next'] is not None, data assert "project owner not found" in data['flash'], data err_msg = "The project owner id should be the same" assert project.owner_id == owner.id, err_msg
def test_project_contact_no_auth(self): """Test Project Contact No Auth.""" admin, owner, user = UserFactory.create_batch(3) project = ProjectFactory.create(owner=owner, short_name='test-app', name='My New Project') # Obtain a CSRF key. csrf = self.get_csrf('/account/signin') # Make a request to the api. url = '/project/' + project.short_name + '/contact?api_key=' + user.api_key res = self.app.get(url, headers={'X-CSRFToken': csrf}) # Verify status code from response. assert res.status_code == 405
def test_query_user(self): """Test API query for user endpoint works""" expected_user, other = UserFactory.create_batch(2) restricted = UserFactory.create(restrict=True) # When querying with a valid existing field which is unique # It should return one correct result if exists res = self.app.get('/api/user?name=%s' % expected_user.name) data = json.loads(res.data) assert len(data) == 1, data assert data[0]['name'] == expected_user.name, data # Trying to change restrict res = self.app.get('/api/user?restrict=true') data = json.loads(res.data) assert len(data) == 2, data for d in data: assert d['name'] != restricted.name, d # And it should return no results if there are no matches res = self.app.get('/api/user?name=Godzilla') data = json.loads(res.data) assert len(data) == 0, data # When querying with a valid existing non-unique field res = self.app.get("/api/user?locale=en") data = json.loads(res.data) # It should return 3 results, as every registered user has locale=en by default assert len(data) == 2, data # And they should be the correct ones assert (data[0]['locale'] == data[1]['locale'] == 'en' and data[0] != data[1]), data # When querying with multiple valid fields res = self.app.get('/api/user?name=%s&locale=en' % expected_user.name) data = json.loads(res.data) # It should find and return one correct result assert len(data) == 1, data assert data[0]['name'] == expected_user.name, data assert data[0]['locale'] == 'en', data # When querying with non-valid fields -- Errors res = self.app.get('/api/user?something_invalid=whatever') err = json.loads(res.data) err_msg = "AttributeError exception should be raised" assert res.status_code == 415, err_msg assert err['action'] == 'GET', err_msg assert err['status'] == 'failed', err_msg assert err['exception_cls'] == 'AttributeError', err_msg
def test_update_announcement(self): """Test API Announcement update post (PUT).""" admin, user = UserFactory.create_batch(2) announcement = AnnouncementFactory.create() # As anon announcement.title = 'new' announcement.body = 'new body' url = '/api/announcement/%s' % announcement.id res = self.app.put(url, data=json.dumps(announcement.dictize())) data = json.loads(res.data) assert res.status_code == 401, res.status_code # As user announcement.title = 'new' announcement.body = 'new body' url = '/api/announcement/%s?api_key=%s' % (announcement.id, user.api_key) data = announcement.dictize() del data['id'] del data['created'] del data['updated'] del data['user_id'] res = self.app.put(url, data=json.dumps(data)) data = json.loads(res.data) assert res.status_code == 403, (res.status_code, res.data) # TODO: as project owner too? # As admin announcement.title = 'new' announcement.body = 'new body' url = '/api/announcement/%s?api_key=%s' % (announcement.id, admin.api_key) payload = announcement.dictize() del payload['user_id'] del payload['created'] del payload['updated'] del payload['id'] payload['published'] = True res = self.app.put(url, data=json.dumps(payload)) data = json.loads(res.data) assert res.status_code == 200, data assert data['title'] == 'new', data assert data['body'] == 'new body', data assert data['updated'] != data['created'], data assert data['published'] is True, data
def test_password_not_required_for_owner(self, mock_user): """Test when the owner wants to contribute to a password protected project is able to do it""" owner = UserFactory.create_batch(2)[1] configure_mock_current_user_from(owner, mock_user) assert owner.admin is False project = ProjectFactory.create(owner=owner) assert project.owner.id == owner.id TaskFactory.create(project=project) project.set_password('mysecret') project_repo.update(project) res = self.app.get('/project/%s/newtask' % project.short_name, follow_redirects=True) assert 'Enter the password to contribute' not in res.data res = self.app.get('/project/%s/task/1' % project.short_name, follow_redirects=True) assert 'Enter the password to contribute' not in res.data
def test_number_of_active_users(self): """Test number of active users in last 30 days""" date_now = datetime.datetime.utcnow() date_60_days_old = (datetime.datetime.utcnow() - datetime.timedelta(60)).isoformat() recent_users = 4 users = UserFactory.create_batch(recent_users) i = recent_users for user in users: TaskRunFactory.create_batch(i, user=user, finish_time=date_now) i -= 1 old_user = UserFactory.create() TaskRunFactory.create(user=old_user, finish_time=date_60_days_old) total_users = stats.number_of_active_users() assert total_users == recent_users, "Total active users in last 30 days should be {}".format(recent_users)
def test_get_existing_token_authenticated_user(self): """Test authenticated user retrieves a given existing token""" user = UserFactory.create_batch(2)[1] user.info = create_tokens_for(user) # If the token exists, it should be retrieved res = self.app.get('/api/token/twitter?api_key=' + user.api_key) data = json.loads(res.data) assert data.get('twitter_token') is not None, data assert data.get( 'twitter_token')['oauth_token'] == 'token-for-%s' % user.name assert data.get('twitter_token' )['oauth_token_secret'] == 'secret-for-%s' % user.name # And no other tokens should assert data.get('facebook_token') is None, data
def test_rank_and_score(self): """Test CACHE USERS rank_and_score returns the correct rank and score""" i = 0 project = ProjectFactory.create() tasks = TaskFactory.create_batch(4, project=project) users = UserFactory.create_batch(4) for user in users: i += 1 taskruns = TaskRunFactory.create_batch(i, user=user, task=tasks[i - 1]) first_in_rank = cached_users.rank_and_score(users[3].id) last_in_rank = cached_users.rank_and_score(users[0].id) print first_in_rank assert first_in_rank['rank'] == 1, first_in_rank['rank'] assert first_in_rank['score'] == 4, first_in_rank['score'] assert last_in_rank['rank'] == 4, last_in_rank['rank'] assert last_in_rank['score'] == 1, last_in_rank['score']
def test_project_contact_no_project(self): """Test Project Contact No Project.""" admin, owner, user = UserFactory.create_batch(3) # Obtain a CSRF key. csrf = self.get_csrf('/account/signin') # Make a request to the api. url = '/project/invalid/contact?api_key=' + user.api_key data = dict(message=u'hello') res = self.app.post(url, headers={'X-CSRFToken': csrf}, content_type='application/json', data=json.dumps(data)) # Verify status code from response. assert res.status_code == 404
def test_proxy_regular_user_has_lock(self, http_get): res = MagicMock() res.json.return_value = {'key': 'testkey'} http_get.return_value = res admin, owner, user = UserFactory.create_batch(3) project = ProjectFactory.create( owner=owner, info={'ext_config': { 'encryption': { 'key_id': 123 } }}) encryption_key = 'testkey' aes = AESWithGCM(encryption_key) content = json.dumps(dict(a=1, b="2")) encrypted_content = aes.encrypt(content) task = TaskFactory.create( project=project, info={'private_json__encrypted_payload': encrypted_content}) signature = signer.dumps({'task_id': task.id}) url = '/fileproxy/encrypted/taskpayload/%s/%s?api_key=%s&task-signature=%s' \ % (project.id, task.id, user.api_key, signature) with patch('pybossa.view.fileproxy.has_lock') as has_lock: has_lock.return_value = True with patch.dict(self.flask_app.config, self.app_config): res = self.app.get(url, follow_redirects=True) assert res.status_code == 200, res.status_code assert res.data == content, res.data with patch('pybossa.view.fileproxy.has_lock') as has_lock: has_lock.return_value = False with patch.dict(self.flask_app.config, self.app_config): res = self.app.get(url, follow_redirects=True) assert res.status_code == 403, res.status_code # coowner can access the task project.owners_ids.append(user.id) with patch('pybossa.view.fileproxy.has_lock') as has_lock: has_lock.return_value = False with patch.dict(self.flask_app.config, self.app_config): res = self.app.get(url, follow_redirects=True) assert res.status_code == 200, res.status_code
def test_query_taskrun(self): """Test API query for taskrun with params works""" admin, owner, user = UserFactory.create_batch(3) owner.subadmin = True project = ProjectFactory.create(owner=owner) task_runs = TaskRunFactory.create_batch(10, project=project) user = UserFactory.create() # Test for real field res = self.app.get('/api/taskrun?project_id=1&all=1&api_key=' + owner.api_key) data = json.loads(res.data) # Should return one result assert len(data) == 10, data # Correct result assert data[0]['project_id'] == 1, data # Valid field but wrong value res = self.app.get('/api/taskrun?project_id=99999999&api_key=' + owner.api_key) data = json.loads(res.data) assert len(data) == 0, data # Multiple fields res = self.app.get('/api/taskrun?project_id=1&task_id=1&api_key=' + owner.api_key) data = json.loads(res.data) # One result assert len(data) == 1, data # Correct result assert data[0]['project_id'] == 1, data assert data[0]['task_id'] == 1, data # Limits res = self.app.get('/api/taskrun?project_id=1&limit=5&api_key=' + owner.api_key) data = json.loads(res.data) for item in data: assert item['project_id'] == 1, item assert len(data) == 5, data # Keyset pagination url = '/api/taskrun?project_id=1&limit=5&last_id=%s&all=1&api_key=%s' % (task_runs[4].id, owner.api_key) res = self.app.get(url) data = json.loads(res.data) for item in data: assert item['project_id'] == 1, item assert len(data) == 5, data assert data[0]['id'] == task_runs[5].id, data[0]['id']
def test_anon_week(self): """Test JOB leaderboard returns anon active week runs.""" db.session.execute('''delete from "user";''') from pybossa.core import user_repo users = UserFactory.create_batch(20) restricted = UserFactory.create(restrict=True) users.append(restricted) for user in users: TaskRunFactory.create(user=user) leaderboard() top_users = get_leaderboard() assert len(top_users) == 20, len(top_users) for u in top_users: assert u['name'] != restricted.name, u results = db.session.execute('select * from users_rank') for r in results: assert r.restrict is False, r
def test_task_with_signature(self, auth): """Get a list of tasks using a list of project_ids.""" auth.return_value = True admin, owner, user = UserFactory.create_batch(3) project = ProjectFactory.create(owner=owner) tasks = TaskFactory.create_batch(2, project=project) url = '/api/task/%s?api_key=%s' with patch.dict(self.flask_app.config, {'ENABLE_ENCRYPTION': True}): for u in [owner, admin]: res = self.app.get(url % (tasks[0].id, u.api_key), follow_redirects=True) assert 'signature' in json.loads(res.data) res = self.app.get(url % (tasks[0].id, user.api_key), follow_redirects=True) assert 'signature' not in json.loads(res.data)
def create_result(self, n_results=1, n_answers=1, owner=None, filter_by=False): if owner: owner = owner else: admin, owner, user = UserFactory.create_batch(3) project = ProjectFactory.create(owner=owner) tasks = [] for i in range(n_results): tasks.append(TaskFactory.create(n_answers=n_answers, project=project)) for i in range(n_answers): for task in tasks: TaskRunFactory.create(task=task, project=project) if filter_by: return result_repo.filter_by(project_id=1) else: return result_repo.get_by(project_id=1)
def test_announcement_post_file(self): """Test API Announcement file upload creation.""" admin, user = UserFactory.create_batch(2) img = (io.BytesIO(b'test'), 'test_file.jpg') payload = dict(file=img, hello='1') # As anon url = '/api/announcement' res = self.app.post(url, data=payload, content_type="multipart/form-data") data = json.loads(res.data) assert res.status_code == 401, data assert data['status_code'] == 401, data # As admin img = (io.BytesIO(b'test'), 'test_file.jpg') payload = dict(file=img, title='title', body='body') url = '/api/announcement?api_key=%s' % admin.api_key res = self.app.post(url, data=payload, content_type="multipart/form-data") data = json.loads(res.data) assert res.status_code == 200, data container = "user_%s" % admin.id assert data['info']['container'] == container, data assert data['info']['file_name'] == 'test_file.jpg', data assert 'test_file.jpg' in data['media_url'], data # As normal user img = (io.BytesIO(b'test'), 'test_file.jpg') payload = dict(file=img) url = '/api/announcement?api_key=%s' % user.api_key res = self.app.post(url, data=payload, content_type="multipart/form-data") data = json.loads(res.data) assert res.status_code == 403, data
def test_newtask(self, get_pwd_manager, auth): """Get a list of tasks using a list of project_ids.""" auth.return_value = True pwd_manager = MagicMock() pwd_manager.password_needed.return_value = False get_pwd_manager.return_value = pwd_manager users = UserFactory.create_batch(3) project = ProjectFactory.create(owner=users[1]) tasks = TaskFactory.create_batch(2, project=project) url = '/api/project/%s/newtask?api_key=%s' with patch.dict(self.flask_app.config, {'ENABLE_ENCRYPTION': True}): for u in users: res = self.app.get(url % (project.id, u.api_key), follow_redirects=True) task = json.loads(res.data) assert 'signature' in task
def test_password_not_required_for_owner(self, mock_user): """Test when the owner wants to contribute to a password protected project is able to do it""" owner = UserFactory.create_batch(2)[1] configure_mock_current_user_from(owner, mock_user) assert owner.admin is False app = AppFactory.create(owner=owner) assert app.owner.id == owner.id TaskFactory.create(app=app) app.set_password('mysecret') db.session.add(app) db.session.commit() res = self.app.get('/app/%s/newtask' % app.short_name, follow_redirects=True) assert 'Enter the password to contribute' not in res.data res = self.app.get('/app/%s/task/1' % app.short_name, follow_redirects=True) assert 'Enter the password to contribute' not in res.data
def test_get_top5_users_24_hours_returns_best_5_users_only(self): users = UserFactory.create_batch(4) restricted = UserFactory.create(restrict=True) users.append(restricted) i = 5 for user in users: TaskRunFactory.create_batch(i, user=user) i -= 1 worst_user = UserFactory.create() top5 = stats.get_top5_users_24_hours() top5_ids = [top['id'] for top in top5] assert len(top5) == 4, len(top5) assert worst_user.id not in top5_ids for i in range(len(top5)): assert users[i].id == top5_ids[i] assert users[i].restrict is False assert users[i].id != restricted.id
def test_06_user_public_profile(self): '''Test PRIVACY user public profile privacy is respected''' admin, user, owner = UserFactory.create_batch(3) # As Anonymou user url = '/account/%s' % owner.name res = self.app.get(url, follow_redirects=True) err_msg = 'Public User Profile page should not be shown to anonymous users' assert 'This feature requires being logged in' in res.data, err_msg # As Authenticated user but NOT ADMIN res = self.app.get(url + '?api_key=%s' % user.api_key, follow_redirects=True) dom = BeautifulSoup(res.data) err_msg = 'Public User Profile page should not be shown to authenticated users' assert dom.find(id='enforce_privacy') is not None, err_msg self.signout # As Authenticated user but ADMIN res = self.app.get(url + '?api_key=%s' % admin.api_key, follow_redirects=True) dom = BeautifulSoup(res.data) err_msg = 'Public User Profile page should be shown to admin users' assert dom.find(id='enforce_privacy') is None, err_msg self.signout()
def test_04_global_stats_index(self): '''Test PRIVACY global stats privacy is respected''' admin, user, owner = UserFactory.create_batch(3) # As Anonymou user url = '/stats' res = self.app.get(url, follow_redirects=True) assert 'This feature requires being logged in' in res.data # As Authenticated user but NOT ADMIN self.signin() res = self.app.get(url + '?api_key=%s' % user.api_key, follow_redirects=True) dom = BeautifulSoup(res.data) err_msg = 'Stats page should not be shown to authenticated users' assert dom.find(id='enforce_privacy') is not None, err_msg self.signout # As Authenticated user but ADMIN res = self.app.get(url + '?api_key=%s' % admin.api_key, follow_redirects=True) dom = BeautifulSoup(res.data) err_msg = 'Stats page should be shown to admin users' assert dom.find(id='enforce_privacy') is None, err_msg self.signout()
def create_user_base(self): """ Create User base if does not exist already """ if not User.objects.all(): users = [] fnames, lnames = self.create_names_list() # Iterate 50 times to create batch profiles of about 10000 users for iteration in range(50): fname = (random.choice(fnames)).lower() lname = (random.choice(lnames)).lower() sname = fname[0] + lname # Create a batch of 200 users passing the short_name users.extend( UserFactory.create_batch(200, first_name=fname, last_name=lname, short_name=sname))
def test_proxy_admin(self, create_connection): admin, owner = UserFactory.create_batch(2) project = ProjectFactory.create(owner=owner) url = '/fileproxy/encrypted/s3/test/%s/file.pdf' % project.id task = TaskFactory.create(project=project, info={'url': url}) signature = signer.dumps({'task_id': task.id}) req_url = '%s?api_key=%s&task-signature=%s' % (url, admin.api_key, signature) encryption_key = 'testkey' aes = AESWithGCM(encryption_key) key = self.get_key(create_connection) key.get_contents_as_string.return_value = aes.encrypt('the content') with patch.dict(self.flask_app.config, {'FILE_ENCRYPTION_KEY': encryption_key}): res = self.app.get(req_url, follow_redirects=True) assert res.status_code == 200, res.status_code assert res.data == 'the content', res.data
def test_app_post_invalid_short_name(self): """Test API project POST returns error if short_name is invalid (i.e. is a name used by the Flask app as a URL endpoint""" users = UserFactory.create_batch(2) CategoryFactory.create() name = u'XXXX Project' data = dict(name=name, short_name='new', description='description', owner_id=1, long_description=u'Long Description\n================') data = json.dumps(data) res = self.app.post('/api/app?api_key=' + users[1].api_key, data=data) error = json.loads(res.data) assert res.status_code == 415, res.status_code assert error['status'] == 'failed', error assert error['action'] == 'POST', error assert error['target'] == 'app', error assert error['exception_cls'] == 'ValueError', error message = "Project short_name is not valid, as it's used by the system." assert error['exception_msg'] == message, error
def test_proxy_key_err(self, http_get, hdfs_get): res = MagicMock() res.json.return_value = {'error': 'an error occurred'} http_get.return_value = res admin, owner = UserFactory.create_batch(2) project = ProjectFactory.create( owner=owner, info={'ext_config': { 'encryption': { 'key_id': 123 } }}) url = '/fileproxy/hdfs/test/%s/file.pdf' % project.id task = TaskFactory.create(project=project, info={'url': url}) signature = signer.dumps({'task_id': task.id}) req_url = '%s?api_key=%s&task-signature=%s' % (url, admin.api_key, signature) with patch.dict(self.flask_app.config, self.app_config): res = self.app.get(req_url, follow_redirects=True) assert res.status_code == 500, res.status_code
def test_delete_for_project_user(self): users = UserFactory.create_batch(2) projects = ProjectFactory.create_batch(2) types = [StatType.confusion_matrix, StatType.accuracy] for p in projects: for u in users: for t in types: stat = PerformanceStatsFactory.create_batch( 2, project_id=p.id, user_id=u.id, stat_type=t) assert len(self.repo.filter_by()) == 16 _type = types[0] user = users[0] project = projects[0] self.repo.bulk_delete(project.id, stat[0].field, _type, user_id=user.id) stats = self.repo.filter_by() assert len(stats) == 14 assert all(stat.user_id != user.id or stat.project_id != project.id or stat.stat_type != _type for stat in stats)