class TestGoogleDriveUtils(OsfTestCase): def setUp(self): super(TestGoogleDriveUtils, self).setUp() self.user = AuthUserFactory() self.user.add_addon('googledrive') self.project = ProjectFactory(creator=self.user) self.project.add_addon('googledrive', Auth(self.user)) self.node_settings = self.project.get_addon('googledrive') self.user_settings = self.user.get_addon('googledrive') oauth_settings = GoogleDriveOAuthSettingsFactory() self.user_settings.oauth_settings = oauth_settings self.node_settings.user_settings = self.user_settings self.node_settings.folder_id = '09120912' self.node_settings.folder_path = 'foo/bar' self.user_settings.save() self.node_settings.save() # Log user in self.app.authenticate(*self.user.auth) def test_serialize_settings_helper_returns_correct_urls(self): result = serialize_settings(self.node_settings, self.user) urls = result['urls'] assert_equal(urls['files'], self.project.web_url_for('collect_file_trees')) assert_equal(urls['config'], self.project.api_url_for('googledrive_config_put')) assert_equal(urls['deauthorize'], self.project.api_url_for('googledrive_deauthorize')) assert_equal(urls['importAuth'], self.project.api_url_for('googledrive_import_user_auth')) # Includes endpoint for fetching folders only # NOTE: Querystring params are in camelCase assert_equal(urls['get_folders'], self.project.api_url_for('googledrive_folders')) def test_serialize_settings_helper_returns_correct_auth_info(self): self.user_settings.access_token = 'abc123' result = serialize_settings(self.node_settings, self.user) assert_equal(result['nodeHasAuth'], self.node_settings.has_auth) assert_true(result['userHasAuth']) assert_true(result['userIsOwner']) def test_serialize_settings_for_user_no_auth(self): no_addon_user = AuthUserFactory() result = serialize_settings(self.node_settings, no_addon_user) assert_false(result['userIsOwner']) assert_false(result['userHasAuth']) def test_googledrive_import_user_auth_returns_serialized_settings(self): self.node_settings.user_settings = None self.node_settings.save() url = api_url_for('googledrive_import_user_auth', pid=self.project._primary_key) res = self.app.put(url, auth=self.user.auth) self.project.reload() self.node_settings.reload() expected_result = serialize_settings(self.node_settings, self.user) result = res.json['result'] assert_equal(result, expected_result)
class TestCommentViews(OsfTestCase): def setUp(self): super(TestCommentViews, self).setUp() self.project = ProjectFactory(is_public=True) self.user = AuthUserFactory() self.project.add_contributor(self.user) self.project.save() self.user.save() def test_view_project_comments_updates_user_comments_view_timestamp(self): url = self.project.api_url_for('update_comments_timestamp') res = self.app.put_json(url, { 'page': 'node', 'rootId': self.project._id }, auth=self.user.auth) self.user.reload() user_timestamp = self.user.comments_viewed_timestamp[self.project._id] view_timestamp = dt.datetime.utcnow() assert_datetime_equal(user_timestamp, view_timestamp) def test_confirm_non_contrib_viewers_dont_have_pid_in_comments_view_timestamp(self): non_contributor = AuthUserFactory() url = self.project.api_url_for('update_comments_timestamp') res = self.app.put_json(url, { 'page': 'node', 'rootId': self.project._id }, auth=self.user.auth) non_contributor.reload() assert_not_in(self.project._id, non_contributor.comments_viewed_timestamp) def test_view_comments_updates_user_comments_view_timestamp_files(self): osfstorage = self.project.get_addon('osfstorage') root_node = osfstorage.get_root() test_file = root_node.append_file('test_file') test_file.create_version(self.user, { 'object': '06d80e', 'service': 'cloud', osfstorage_settings.WATERBUTLER_RESOURCE: 'osf', }, { 'size': 1337, 'contentType': 'img/png' }).save() url = self.project.api_url_for('update_comments_timestamp') res = self.app.put_json(url, { 'page': 'files', 'rootId': test_file._id }, auth=self.user.auth) self.user.reload() user_timestamp = self.user.comments_viewed_timestamp[test_file._id] view_timestamp = dt.datetime.utcnow() assert_datetime_equal(user_timestamp, view_timestamp)
class TestCommentViews(OsfTestCase): def setUp(self): super(TestCommentViews, self).setUp() self.project = ProjectFactory(is_public=True) self.user = AuthUserFactory() self.project.add_contributor(self.user) self.project.save() self.user.save() def test_view_project_comments_updates_user_comments_view_timestamp(self): url = self.project.api_url_for('update_comments_timestamp') res = self.app.put_json(url, { 'page': 'node', 'rootId': self.project._id }, auth=self.user.auth) self.user.reload() user_timestamp = self.user.comments_viewed_timestamp[self.project._id]['node'] view_timestamp = dt.datetime.utcnow() assert_datetime_equal(user_timestamp, view_timestamp) def test_confirm_non_contrib_viewers_dont_have_pid_in_comments_view_timestamp(self): non_contributor = AuthUserFactory() url = self.project.api_url_for('update_comments_timestamp') res = self.app.put_json(url, { 'page': 'node', 'rootId': self.project._id }, auth=self.user.auth) non_contributor.reload() assert_not_in(self.project._id, non_contributor.comments_viewed_timestamp) def test_view_comments_updates_user_comments_view_timestamp_files(self): osfstorage = self.project.get_addon('osfstorage') root_node = osfstorage.get_root() test_file = root_node.append_file('test_file') test_file.create_version(self.user, { 'object': '06d80e', 'service': 'cloud', osfstorage_settings.WATERBUTLER_RESOURCE: 'osf', }, { 'size': 1337, 'contentType': 'img/png' }).save() url = self.project.api_url_for('update_comments_timestamp') res = self.app.put_json(url, { 'page': 'files', 'rootId': test_file._id }, auth=self.user.auth) self.user.reload() user_timestamp = self.user.comments_viewed_timestamp[self.project._id]['files'][test_file._id] view_timestamp = dt.datetime.utcnow() assert_datetime_equal(user_timestamp, view_timestamp)
class TestWikiDelete(OsfTestCase): def setUp(self): super(TestWikiDelete, self).setUp() self.project = ProjectFactory(is_public=True) api_key = ApiKeyFactory() self.project.creator.api_keys.append(api_key) self.project.creator.save() self.consolidate_auth = Auth(user=self.project.creator, api_key=api_key) self.auth = ('test', api_key._primary_key) self.project.update_node_wiki('Elephants', 'Hello Elephants', self.consolidate_auth) self.project.update_node_wiki('Lions', 'Hello Lions', self.consolidate_auth) self.elephant_wiki = self.project.get_wiki_page('Elephants') self.lion_wiki = self.project.get_wiki_page('Lions') @mock.patch('website.addons.wiki.utils.broadcast_to_sharejs') def test_project_wiki_delete(self, mock_shrejs): assert_in('elephants', self.project.wiki_pages_current) url = self.project.api_url_for( 'project_wiki_delete', wname='elephants' ) self.app.delete( url, auth=self.auth ) self.project.reload() assert_not_in('elephants', self.project.wiki_pages_current) @mock.patch('website.addons.wiki.utils.broadcast_to_sharejs') def test_project_wiki_delete_w_valid_special_characters(self, mock_sharejs): # TODO: Need to understand why calling update_node_wiki with failure causes transaction rollback issue later # with assert_raises(NameInvalidError): # self.project.update_node_wiki(SPECIAL_CHARACTERS_ALL, 'Hello Special Characters', self.consolidate_auth) self.project.update_node_wiki(SPECIAL_CHARACTERS_ALLOWED, 'Hello Special Characters', self.consolidate_auth) self.special_characters_wiki = self.project.get_wiki_page(SPECIAL_CHARACTERS_ALLOWED) assert_in(to_mongo_key(SPECIAL_CHARACTERS_ALLOWED), self.project.wiki_pages_current) url = self.project.api_url_for( 'project_wiki_delete', wname=SPECIAL_CHARACTERS_ALLOWED ) self.app.delete( url, auth=self.auth ) self.project.reload() assert_not_in(to_mongo_key(SPECIAL_CHARACTERS_ALLOWED), self.project.wiki_pages_current)
def test_POST_register_embargo_does_not_make_project_or_children_public(self, mock_enqueue): public_project = ProjectFactory(creator=self.user, is_public=True) component = NodeFactory(creator=self.user, parent=public_project, title="Component", is_public=True) subproject = ProjectFactory(creator=self.user, parent=public_project, title="Subproject", is_public=True) subproject_component = NodeFactory(creator=self.user, parent=subproject, title="Subcomponent", is_public=True) res = self.app.post( public_project.api_url_for("node_register_template_page_post", template=u"Open-Ended_Registration"), self.valid_embargo_payload, content_type="application/json", auth=self.user.auth, ) public_project.reload() assert_equal(res.status_code, 201) # Last node directly registered from self.project registration = Node.load(public_project.node__registrations[-1]) assert_true(registration.is_registration) assert_false(registration.is_public) assert_true(registration.is_pending_embargo_for_existing_registration) assert_is_not_none(registration.embargo) for node in registration.get_descendants_recursive(): assert_true(node.is_registration) assert_false(node.is_public)
def test_rmap_post_non_public_project_should_error(self): private_project = ProjectFactory(creator=self.user, is_public=False) url = private_project.api_url_for('node_rmap_post') res = self.app.post_json(url, {}, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 400)
def test_get_most_in_common_contributors(self): # project 1 (contrib 1, contrib 2, unreg_contrib 3) # - component 1 (contrib 1) # project 2 - add should show contrib 1 first (2 links), contrib 2 second (1 link) contributor_1 = AuthUserFactory() contributor_2 = AuthUserFactory() self.project.add_contributor(contributor_1, auth=self.auth) self.project.add_contributor(contributor_2, auth=self.auth) # has one unregistered contributor self.project.add_unregistered_contributor( fullname=fake.name(), email=fake.email(), auth=self.auth, ) self.project.save() component = NodeFactory(parent=self.project, creator=self.user) component.add_contributor(contributor_1, auth=self.auth) component.save() project_2 = ProjectFactory(creator=self.user) project_2.add_contributor(contributor_1, auth=self.auth) url = project_2.api_url_for('get_most_in_common_contributors') res = self.app.get(url, auth=self.user.auth) project_2.reload() res_contribs = res.json['contributors'] assert_equal(len(res.json['contributors']), 2) assert_equal(contributor_1._id, res_contribs[0]['id']) assert_equal(res_contribs[0]['n_projects_in_common'], 2) assert_equal(contributor_2._id, res_contribs[1]['id']) assert_equal(res_contribs[1]['n_projects_in_common'], 1)
class TestGoogleDriveHgridViews(OsfTestCase): def setUp(self): super(TestGoogleDriveHgridViews, self).setUp() self.user = AuthUserFactory() self.user.add_addon('googledrive') self.project = ProjectFactory(creator=self.user) self.project.add_addon('googledrive', Auth(self.user)) self.node_settings = self.project.get_addon('googledrive') self.user_settings = self.user.get_addon('googledrive') self.node_settings.user_settings = self.user_settings self.user_settings.save() self.node_settings.save() # Log user in self.app.authenticate(*self.user.auth) @mock.patch('website.addons.googledrive.views.hgrid.GoogleDriveClient.folders') def test_googledrive_folders(self, mock_drive_client_folders): folderId = '12345' mock_drive_client_folders.return_value = mock_folders['items'] url = api_url_for('googledrive_folders', pid=self.project._primary_key, folderId=folderId) res = self.app.get(url, auth=self.user.auth) assert_equal(res.status_code, 200) assert_equal(len(res.json), len(mock_folders['items'])) @mock.patch('website.addons.googledrive.views.hgrid.GoogleDriveClient.about') def test_googledrive_folders_returns_only_root(self, mock_about): mock_about.return_value = {'rootFolderId': '24601'} url = self.project.api_url_for('googledrive_folders') res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json), 1) assert_equal(res.status_code, 200) assert_equal(res.json[0]['id'], '24601')
class TestCreateBucket(OsfTestCase): def setUp(self): super(TestCreateBucket, self).setUp() self.user = AuthUserFactory() self.consolidated_auth = Auth(user=self.user) self.auth = ('test', self.user.api_keys[0]._primary_key) self.project = ProjectFactory(creator=self.user) self.project.add_addon('s3', auth=self.consolidated_auth) self.project.creator.add_addon('s3') self.user_settings = self.user.get_addon('s3') self.user_settings.access_key = 'We-Will-Rock-You' self.user_settings.secret_key = 'Idontknowanyqueensongs' self.user_settings.save() self.node_settings = self.project.get_addon('s3') self.node_settings.bucket = 'Sheer-Heart-Attack' self.node_settings.user_settings = self.project.creator.get_addon('s3') self.node_settings.save() def test_bad_names(self): assert_false(validate_bucket_name('bogus naMe')) assert_false(validate_bucket_name('')) assert_false(validate_bucket_name('no')) assert_false(validate_bucket_name('.cantstartwithp')) assert_false(validate_bucket_name('or.endwith.')) assert_false(validate_bucket_name('..nodoubles')) assert_false(validate_bucket_name('no_unders_in')) def test_names(self): assert_true(validate_bucket_name('imagoodname')) assert_true(validate_bucket_name('still.passing')) assert_true(validate_bucket_name('can-have-dashes')) assert_true(validate_bucket_name('kinda.name.spaced')) @mock.patch('website.addons.s3.views.crud.create_bucket') @mock.patch('website.addons.s3.utils.get_bucket_drop_down') def test_create_bucket_pass(self, mock_make, mock_dropdown): mock_make.return_value = True mock_dropdown.return_value = ['mybucket'] url = self.project.api_url_for('create_new_bucket') ret = self.app.post_json(url, {'bucket_name': 'doesntevenmatter'}, auth=self.user.auth) assert_equals(ret.status_int, http.OK) @mock.patch('website.addons.s3.views.crud.create_bucket') def test_create_bucket_fail(self, mock_make): error = S3ResponseError(418, 'because Im a test') error.message = 'This should work' mock_make.side_effect = error url = "/api/v1/project/{0}/s3/newbucket/".format(self.project._id) ret = self.app.post_json(url, {'bucket_name': 'doesntevenmatter'}, auth=self.user.auth, expect_errors=True) assert_equals(ret.body, '{"message": "This should work", "title": "Problem connecting to S3"}')
def test_POST_register_embargo_does_not_make_project_or_children_public( self, mock_enqueue): public_project = ProjectFactory(creator=self.user, is_public=True) component = NodeFactory(creator=self.user, parent=public_project, title='Component', is_public=True) subproject = ProjectFactory(creator=self.user, parent=public_project, title='Subproject', is_public=True) subproject_component = NodeFactory(creator=self.user, parent=subproject, title='Subcomponent', is_public=True) res = self.app.post(public_project.api_url_for( 'node_register_template_page_post', template=u'Open-Ended_Registration'), self.valid_embargo_payload, content_type='application/json', auth=self.user.auth) public_project.reload() assert_equal(res.status_code, 201) # Last node directly registered from self.project registration = Node.load(public_project.node__registrations[-1]) assert_true(registration.is_registration) assert_false(registration.is_public) assert_true(registration.is_pending_embargo_for_existing_registration) assert_is_not_none(registration.embargo) for node in registration.get_descendants_recursive(): assert_true(node.is_registration) assert_false(node.is_public)
def test_cannot_rename_wiki_page_to_home(self): user = AuthUserFactory() # A fresh project where the 'home' wiki page has no content project = ProjectFactory(creator=user) project.update_node_wiki('Hello', 'hello world', Auth(user=user)) url = project.api_url_for('project_wiki_rename', wname=to_mongo_key('Hello')) res = self.app.put_json(url, {'value': 'home'}, auth=user.auth, expect_errors=True) assert_equal(res.status_code, 409)
class RegistrationsTestBase(OsfTestCase): def setUp(self): super(RegistrationsTestBase, self).setUp() self.user = AuthUserFactory() self.auth = Auth(self.user) self.node = ProjectFactory(creator=self.user) self.non_admin = AuthUserFactory() self.node.add_contributor( self.non_admin, permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS, auth=self.auth, save=True ) self.non_contrib = AuthUserFactory() MetaSchema.remove() ensure_schemas() self.meta_schema = MetaSchema.find_one( Q('name', 'eq', 'Open-Ended Registration') & Q('schema_version', 'eq', 2) ) self.draft = DraftRegistrationFactory( initiator=self.user, branched_from=self.node, registration_schema=self.meta_schema, registration_metadata={ 'summary': {'value': 'Some airy'} } ) current_month = dt.datetime.now().strftime("%B") current_year = dt.datetime.now().strftime("%Y") valid_date = dt.datetime.now() + dt.timedelta(days=180) self.embargo_payload = { u'embargoEndDate': unicode(valid_date.strftime('%a, %d, %B %Y %H:%M:%S')) + u' GMT', u'registrationChoice': 'embargo' } self.invalid_embargo_date_payload = { u'embargoEndDate': u"Thu, 01 {month} {year} 05:00:00 GMT".format( month=current_month, year=str(int(current_year) - 1) ), u'registrationChoice': 'embargo' } self.immediate_payload = { 'registrationChoice': 'immediate' } self.invalid_payload = { 'registrationChoice': 'foobar' } def draft_url(self, view_name): return self.node.web_url_for(view_name, draft_id=self.draft._id) def draft_api_url(self, view_name): return self.node.api_url_for(view_name, draft_id=self.draft._id)
def test_import_auth_invalid_account(self): ea = self.ExternalAccountFactory() node = ProjectFactory(creator=self.user) node.add_addon(self.ADDON_SHORT_NAME, auth=self.auth) node.save() url = node.api_url_for("{0}_import_auth".format(self.ADDON_SHORT_NAME)) res = self.app.put_json(url, {"external_account_id": ea._id}, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, http.FORBIDDEN)
def test_add_log_no_addon(self): path = "pizza" node = ProjectFactory(creator=self.user) url = node.api_url_for("create_waterbutler_log") payload = self.build_payload(metadata={"path": path}) nlogs = len(node.logs) res = self.app.put_json(url, payload, headers={"Content-Type": "application/json"}, expect_errors=True) assert_equal(res.status_code, 400) self.node.reload() assert_equal(len(node.logs), nlogs)
class TestCommentViews(OsfTestCase): def setUp(self): super(TestCommentViews, self).setUp() self.project = ProjectFactory(is_public=True) self.user = AuthUserFactory() self.project.add_contributor(self.user) self.project.save() self.user.save() def test_view_project_comments_updates_user_comments_view_timestamp(self): url = self.project.api_url_for("update_comments_timestamp") res = self.app.put_json(url, {"page": "node", "rootId": self.project._id}, auth=self.user.auth) self.user.reload() user_timestamp = self.user.comments_viewed_timestamp[self.project._id] view_timestamp = dt.datetime.utcnow() assert_datetime_equal(user_timestamp, view_timestamp) def test_confirm_non_contrib_viewers_dont_have_pid_in_comments_view_timestamp(self): non_contributor = AuthUserFactory() url = self.project.api_url_for("update_comments_timestamp") res = self.app.put_json(url, {"page": "node", "rootId": self.project._id}, auth=self.user.auth) non_contributor.reload() assert_not_in(self.project._id, non_contributor.comments_viewed_timestamp) def test_view_comments_updates_user_comments_view_timestamp_files(self): osfstorage = self.project.get_addon("osfstorage") root_node = osfstorage.get_root() test_file = root_node.append_file("test_file") test_file.create_version( self.user, {"object": "06d80e", "service": "cloud", osfstorage_settings.WATERBUTLER_RESOURCE: "osf"}, {"size": 1337, "contentType": "img/png"}, ).save() url = self.project.api_url_for("update_comments_timestamp") res = self.app.put_json(url, {"page": "files", "rootId": test_file._id}, auth=self.user.auth) self.user.reload() user_timestamp = self.user.comments_viewed_timestamp[test_file._id] view_timestamp = dt.datetime.utcnow() assert_datetime_equal(user_timestamp, view_timestamp)
def test_build_dropbox_urls_file(self): node = ProjectFactory() fake_metadata = mock_responses['metadata_single'] result = utils.build_dropbox_urls(fake_metadata, node) path = utils.clean_path(fake_metadata['path']) assert_equal(result['download'], node.web_url_for('dropbox_download', path=path)) assert_equal(result['view'], node.web_url_for('dropbox_view_file', path=path)) assert_equal(result['delete'], node.api_url_for('dropbox_delete_file', path=path))
def test_import_auth_invalid_account(self): ea = self.ExternalAccountFactory() node = ProjectFactory(creator=self.user) node.add_addon(self.ADDON_SHORT_NAME, auth=self.auth) node.save() url = node.api_url_for('{0}_import_auth'.format(self.ADDON_SHORT_NAME)) res = self.app.put_json(url, {'external_account_id': ea._id}, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, http.FORBIDDEN)
class TestViewHelpers(OsfTestCase): def setUp(self): super(TestViewHelpers, self).setUp() self.project = ProjectFactory() self.wname = 'New page' self.project.update_node_wiki(self.wname, 'some content', Auth(self.project.creator)) def test_get_wiki_web_urls(self): urls = _get_wiki_web_urls(self.project, self.wname) assert_equal(urls['base'], self.project.web_url_for('project_wiki_home', _guid=True)) assert_equal(urls['edit'], self.project.web_url_for('project_wiki_view', wname=self.wname, _guid=True)) assert_equal(urls['home'], self.project.web_url_for('project_wiki_home', _guid=True)) assert_equal(urls['page'], self.project.web_url_for('project_wiki_view', wname=self.wname, _guid=True)) def test_get_wiki_api_urls(self): urls = _get_wiki_api_urls(self.project, self.wname) assert_equal(urls['base'], self.project.api_url_for('project_wiki_home')) assert_equal(urls['delete'], self.project.api_url_for('project_wiki_delete', wname=self.wname)) assert_equal(urls['rename'], self.project.api_url_for('project_wiki_rename', wname=self.wname)) assert_equal(urls['content'], self.project.api_url_for('wiki_page_content', wname=self.wname))
def test_import_auth_cant_write_node(self): ea = self.ExternalAccountFactory() user = AuthUserFactory() user.add_addon(self.ADDON_SHORT_NAME, auth=Auth(user)) user.external_accounts.append(ea) user.save() node = ProjectFactory(creator=self.user) node.add_contributor(user, permissions=[permissions.READ], auth=self.auth, save=True) node.add_addon(self.ADDON_SHORT_NAME, auth=self.auth) node.save() url = node.api_url_for("{0}_import_auth".format(self.ADDON_SHORT_NAME)) res = self.app.put_json(url, {"external_account_id": ea._id}, auth=user.auth, expect_errors=True) assert_equal(res.status_code, http.FORBIDDEN)
def test_add_log_no_addon(self): path = 'pizza' node = ProjectFactory(creator=self.user) url = node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}) nlogs = len(node.logs) res = self.test_app.put_json( url, payload, headers={'Content-Type': 'application/json'}, expect_errors=True, ) assert_equal(res.status_code, 400) self.node.reload() assert_equal(len(node.logs), nlogs)
def test_import_auth_cant_write_node(self): ea = self.ExternalAccountFactory() user = AuthUserFactory() user.add_addon(self.ADDON_SHORT_NAME, auth=Auth(user)) user.external_accounts.append(ea) user.save() node = ProjectFactory(creator=self.user) node.add_contributor(user, permissions=[permissions.READ], auth=self.auth, save=True) node.add_addon(self.ADDON_SHORT_NAME, auth=self.auth) node.save() url = node.api_url_for('{0}_import_auth'.format(self.ADDON_SHORT_NAME)) res = self.app.put_json(url, { 'external_account_id': ea._id }, auth=user.auth, expect_errors=True) assert_equal(res.status_code, http.FORBIDDEN)
def test_build_dropbox_urls_file(self): node = ProjectFactory() fake_metadata = mock_responses['metadata_single'] result = utils.build_dropbox_urls(fake_metadata, node) path = utils.clean_path(fake_metadata['path']) assert_equal( result['download'], node.web_url_for('dropbox_download', path=path) ) assert_equal( result['view'], node.web_url_for('dropbox_view_file', path=path) ) assert_equal( result['delete'], node.api_url_for('dropbox_delete_file', path=path) )
def test_find_unread_includes_edited_comments(self): project = ProjectFactory() user = AuthUserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator) url = project.api_url_for('update_comments_timestamp') payload = {'page': 'node', 'rootId': project._id} res = self.app.put_json(url, payload, auth=user.auth) user.reload() n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 0) # Edit previously read comment comment.edit(auth=Auth(project.creator), content='edited', save=True) n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 1)
def test_import_auth(self): ea = self.ExternalAccountFactory() self.user.external_accounts.append(ea) self.user.save() node = ProjectFactory(creator=self.user) node_settings = node.get_or_add_addon(self.ADDON_SHORT_NAME, auth=Auth(self.user)) node.save() url = node.api_url_for("{0}_import_auth".format(self.ADDON_SHORT_NAME)) res = self.app.put_json(url, {"external_account_id": ea._id}, auth=self.user.auth) assert_equal(res.status_code, http.OK) assert_in("result", res.json) node_settings.reload() assert_equal(node_settings.external_account._id, ea._id) node.reload() last_log = node.logs[-1] assert_equal(last_log.action, "{0}_node_authorized".format(self.ADDON_SHORT_NAME))
def test_find_unread_includes_edited_comments(self): project = ProjectFactory() user = AuthUserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator) url = project.api_url_for("update_comments_timestamp") payload = {"page": "node", "rootId": project._id} res = self.app.put_json(url, payload, auth=user.auth) user.reload() n_unread = Comment.find_n_unread(user=user, node=project, page="node") assert_equal(n_unread, 0) # Edit previously read comment comment.edit(auth=Auth(project.creator), content="edited", save=True) n_unread = Comment.find_n_unread(user=user, node=project, page="node") assert_equal(n_unread, 1)
def test_import_auth(self): ea = self.ExternalAccountFactory() self.user.external_accounts.append(ea) self.user.save() node = ProjectFactory(creator=self.user) node_settings = node.get_or_add_addon(self.ADDON_SHORT_NAME, auth=Auth(self.user)) node.save() url = node.api_url_for('{0}_import_auth'.format(self.ADDON_SHORT_NAME)) res = self.app.put_json(url, { 'external_account_id': ea._id }, auth=self.user.auth) assert_equal(res.status_code, http.OK) assert_in('result', res.json) node_settings.reload() assert_equal(node_settings.external_account._id, ea._id) node.reload() last_log = node.logs.latest() assert_equal(last_log.action, '{0}_node_authorized'.format(self.ADDON_SHORT_NAME))
def test_POST_register_make_public_immediately_creates_private_pending_registration_for_public_project(self, mock_enqueue): public_project = ProjectFactory(is_public=True, creator=self.user) component = NodeFactory( creator=self.user, parent=public_project, title='Component', is_public=True ) subproject = ProjectFactory( creator=self.user, parent=public_project, title='Subproject', is_public=True ) subproject_component = NodeFactory( creator=self.user, parent=subproject, title='Subcomponent', is_public=True ) res = self.app.post( public_project.api_url_for('node_register_template_page_post', template=u'Open-Ended_Registration'), self.valid_make_public_payload, content_type='application/json', auth=self.user.auth ) public_project.reload() assert_equal(res.status_code, 201) assert_equal(res.json['urls']['registrations'], public_project.web_url_for('node_registrations')) # Last node directly registered from self.project registration = Node.load(public_project.node__registrations[-1]) assert_true(registration.is_registration) assert_false(registration.is_public) for node in registration.get_descendants_recursive(): assert_true(node.is_registration) assert_false(node.is_public)
class TestGoogleDriveAuthViews(OsfTestCase): def setUp(self): super(TestGoogleDriveAuthViews, self).setUp() self.user = AuthUserFactory() self.user.add_addon('googledrive') self.project = ProjectFactory(creator=self.user) self.project.add_addon('googledrive', Auth(self.user)) self.node_settings = self.project.get_addon('googledrive') self.user_settings = self.user.get_addon('googledrive') oauth_settings = GoogleDriveOAuthSettingsFactory() self.user_settings.oauth_settings = oauth_settings self.node_settings.user_settings = self.user_settings # Log user in self.app.authenticate(*self.user.auth) self.flow = mock.Mock() self.credentials = mock.Mock() # Class variables(self) are usually used to mark mock variables. Can be removed later. @mock.patch('website.addons.googledrive.views.auth.GoogleAuthClient.start') def test_googledrive_oauth_start(self, mock_auth_client_start): url = api_url_for('googledrive_oauth_start_user', Auth(self.user)) authorization_url = 'https://fake.domain/' state = 'secure state' mock_auth_client_start.return_value = (authorization_url, state) res = self.app.post(url) assert_true(res.json['url'], authorization_url) @mock.patch('website.addons.googledrive.views.auth.GoogleAuthClient.userinfo') @mock.patch('website.addons.googledrive.views.auth.GoogleAuthClient.finish') @mock.patch('website.addons.googledrive.views.auth.session') def test_googledrive_oauth_finish(self, mock_session, mock_auth_client_finish, mock_auth_client_userinfo): user_no_addon = AuthUserFactory() nid = self.project._primary_key state = '1234' mock_session.data = { 'googledrive_auth_nid': nid, 'googledrive_auth_state': state, } mock_auth_client_finish.return_value = { 'access_token': '1111', 'refresh_token': '2222', 'expires_at': time.time() + 3600, } mock_auth_client_userinfo.return_value = { 'sub': 'unique id', 'name': 'test-user', } url = api_url_for('googledrive_oauth_finish', user_no_addon.auth, nid=self.project._primary_key, code='1234', state=state) res = self.app.get(url) assert_is_redirect(res) @mock.patch('website.addons.googledrive.views.auth.flash') def test_googledrive_oauth_finish_cancelled(self, mock_flash): user_no_addon = AuthUserFactory() url = api_url_for( 'googledrive_oauth_finish', user_no_addon.auth, nid=self.project._primary_key, code='1234', state='3322', error='User declined!' ) res = self.app.get(url) assert_is_redirect(res) mock_flash.assert_called_once() @mock.patch('website.addons.googledrive.views.auth.GoogleAuthClient.userinfo') @mock.patch('website.addons.googledrive.views.auth.GoogleAuthClient.finish') @mock.patch('website.addons.googledrive.views.auth.session') def test_googledrive_oauth_finish_user_only(self, mock_session, mock_auth_client_finish, mock_auth_client_userinfo): user_no_addon = AuthUserFactory() state = '1234' mock_session.data = { 'googledrive_auth_state': state, } mock_auth_client_finish.return_value = { 'access_token': '1111', 'refresh_token': '2222', 'expires_at': time.time() + 3600, } mock_auth_client_userinfo.return_value = { 'sub': 'unique id', 'name': 'test-user', } url = api_url_for('googledrive_oauth_finish', user_no_addon.auth, code='1234', state=state) res = self.app.get(url) assert_is_redirect(res) @mock.patch('website.addons.googledrive.views.auth.GoogleAuthClient.revoke') def test_googledrive_oauth_delete_user(self, mock_auth_client_revoke): self.user_settings.access_token = 'abc123' self.user_settings.save() assert_true(self.user_settings.has_auth) self.user.save() url = api_url_for('googledrive_oauth_delete_user') self.app.delete(url) self.user_settings.reload() mock_auth_client_revoke.assert_called_once() assert_false(self.user_settings.has_auth) def test_googledrive_deauthorize(self): self.node_settings.folder_id = 'foobar' self.node_settings.folder_path = 'My folder' self.node_settings.save() url = self.project.api_url_for('googledrive_deauthorize') self.app.delete(url) self.project.reload() self.node_settings.reload() assert_false(self.node_settings.has_auth) assert_is(self.node_settings.folder_id, None) assert_is(self.node_settings.folder_path, None) assert_is(self.node_settings.user_settings, None)
class TestGoogleDriveConfigViews(OsfTestCase): def setUp(self): super(TestGoogleDriveConfigViews, self).setUp() self.user = AuthUserFactory() self.user.add_addon('googledrive') self.user_settings = self.user.get_addon('googledrive') self.project = ProjectFactory(creator=self.user) self.project.add_addon('googledrive', Auth(self.user)) self.node_settings = self.project.get_addon('googledrive') self.node_settings.user_settings = self.user_settings oauth_settings = GoogleDriveOAuthSettingsFactory() oauth_settings.save() self.user_settings.oauth_settings = oauth_settings self.node_settings.save() # Log user in self.app.authenticate(*self.user.auth) def test_drive_user_config_get_returns_correct_urls(self): self.user.add_addon('googledrive') url = api_url_for('googledrive_user_config_get', Auth(self.user)) res = self.app.get(url) assert_equal(res.status_code, 200) result = res.json['result']['urls'] assert_true(result['create'], api_url_for('googledrive_oauth_start_user')) assert_true(result['delete'], api_url_for('googledrive_oauth_delete_user')) def test_drive_user_config_get_has_auth(self): self.user.add_addon('googledrive') user_settings = self.user.get_addon('googledrive') user_settings.access_token = 'abc123' user_settings.save() url = api_url_for('googledrive_user_config_get', Auth(self.user)) res = self.app.get(url) assert_equal(res.status_code, 200) result = res.json['result'] assert_true(result['userHasAuth']) def test_drive_user_config_get_not_has_auth(self): self.user_settings.access_token = None self.user_settings.save() url = api_url_for('googledrive_user_config_get', Auth(self.user)) res = self.app.get(url) assert_equal(res.status_code, 200) result = res.json['result'] assert_false(result['userHasAuth']) # TODO def test_googledrive_config_put(self): url = self.project.api_url_for('googledrive_config_put') selected = { 'path': 'Google Drive/ My Folder', 'name': 'Google Drive/ My Folder', 'id': '12345' } # Can set folder through API call res = self.app.put_json(url, {'selected': selected}, auth=self.user.auth) assert_equal(res.status_code, 200) self.node_settings.reload() self.project.reload() # Folder was set assert_equal(self.node_settings.folder_name, ' My Folder') # A log event was created last_log = self.project.logs[-1] assert_equal(last_log.action, 'googledrive_folder_selected') params = last_log.params assert_equal(params['folder'], self.node_settings.folder_name)
class RegistrationEmbargoViewsTestCase(OsfTestCase): def setUp(self): super(RegistrationEmbargoViewsTestCase, self).setUp() ensure_schemas() self.user = AuthUserFactory() self.project = ProjectFactory(creator=self.user) self.registration = RegistrationFactory(project=self.project, creator=self.user) current_month = datetime.datetime.now().strftime("%B") current_year = datetime.datetime.now().strftime("%Y") self.valid_make_public_payload = json.dumps({ u'embargoEndDate': u'Fri, 01, {month} {year} 00:00:00 GMT'.format(month=current_month, year=current_year), u'registrationChoice': 'immediate', u'summary': unicode(fake.sentence()) }) valid_date = datetime.datetime.now() + datetime.timedelta(days=180) self.valid_embargo_payload = json.dumps({ u'embargoEndDate': unicode(valid_date.strftime('%a, %d, %B %Y %H:%M:%S')) + u' GMT', u'registrationChoice': 'embargo', u'summary': unicode(fake.sentence()) }) self.invalid_embargo_date_payload = json.dumps({ u'embargoEndDate': u"Thu, 01 {month} {year} 05:00:00 GMT".format( month=current_month, year=str(int(current_year) - 1)), u'registrationChoice': 'embargo', u'summary': unicode(fake.sentence()) }) @mock.patch('framework.tasks.handlers.enqueue_task') def test_POST_register_make_public_immediately_creates_registration_approval( self, mock_enqueue): res = self.app.post(self.project.api_url_for( 'node_register_template_page_post', template=u'Open-Ended_Registration'), self.valid_make_public_payload, content_type='application/json', auth=self.user.auth) assert_equal(res.status_code, 201) registration = Node.find().sort('-registered_date')[0] assert_true(registration.is_registration) assert_not_equal(registration.registration_approval, None) # Regression test for https://openscience.atlassian.net/browse/OSF-5039 @mock.patch('framework.tasks.handlers.enqueue_task') def test_POST_register_make_public_immediately_creates_private_pending_registration_for_public_project( self, mock_enqueue): public_project = ProjectFactory(is_public=True, creator=self.user) component = NodeFactory(creator=self.user, parent=public_project, title='Component', is_public=True) subproject = ProjectFactory(creator=self.user, parent=public_project, title='Subproject', is_public=True) subproject_component = NodeFactory(creator=self.user, parent=subproject, title='Subcomponent', is_public=True) res = self.app.post(public_project.api_url_for( 'node_register_template_page_post', template=u'Open-Ended_Registration'), self.valid_make_public_payload, content_type='application/json', auth=self.user.auth) public_project.reload() assert_equal(res.status_code, 201) # Last node directly registered from self.project registration = Node.load(public_project.node__registrations[-1]) assert_true(registration.is_registration) assert_false(registration.is_public) for node in registration.get_descendants_recursive(): assert_true(node.is_registration) assert_false(node.is_public) @mock.patch('framework.tasks.handlers.enqueue_task') def test_POST_register_make_public_does_not_make_children_public( self, mock_enqueue): component = NodeFactory(creator=self.user, parent=self.project, title='Component') subproject = ProjectFactory(creator=self.user, parent=self.project, title='Subproject') subproject_component = NodeFactory(creator=self.user, parent=subproject, title='Subcomponent') res = self.app.post(self.project.api_url_for( 'node_register_template_page_post', template=u'Open-Ended_Registration'), self.valid_make_public_payload, content_type='application/json', auth=self.user.auth) self.project.reload() # Last node directly registered from self.project registration = Node.load(self.project.node__registrations[-1]) assert_false(registration.is_public) for node in registration.get_descendants_recursive(): assert_true(node.is_registration) assert_false(node.is_public) @mock.patch('framework.tasks.handlers.enqueue_task') def test_POST_register_embargo_is_not_public(self, mock_enqueue): res = self.app.post(self.project.api_url_for( 'node_register_template_page_post', template=u'Open-Ended_Registration'), self.valid_embargo_payload, content_type='application/json', auth=self.user.auth) assert_equal(res.status_code, 201) registration = Node.find().sort('-registered_date')[0] assert_true(registration.is_registration) assert_false(registration.is_public) assert_true(registration.is_pending_embargo_for_existing_registration) assert_is_not_none(registration.embargo) # Regression test for https://openscience.atlassian.net/browse/OSF-5071 @mock.patch('framework.tasks.handlers.enqueue_task') def test_POST_register_embargo_does_not_make_project_or_children_public( self, mock_enqueue): public_project = ProjectFactory(creator=self.user, is_public=True) component = NodeFactory(creator=self.user, parent=public_project, title='Component', is_public=True) subproject = ProjectFactory(creator=self.user, parent=public_project, title='Subproject', is_public=True) subproject_component = NodeFactory(creator=self.user, parent=subproject, title='Subcomponent', is_public=True) res = self.app.post(public_project.api_url_for( 'node_register_template_page_post', template=u'Open-Ended_Registration'), self.valid_embargo_payload, content_type='application/json', auth=self.user.auth) public_project.reload() assert_equal(res.status_code, 201) # Last node directly registered from self.project registration = Node.load(public_project.node__registrations[-1]) assert_true(registration.is_registration) assert_false(registration.is_public) assert_true(registration.is_pending_embargo_for_existing_registration) assert_is_not_none(registration.embargo) for node in registration.get_descendants_recursive(): assert_true(node.is_registration) assert_false(node.is_public) @mock.patch('framework.tasks.handlers.enqueue_task') def test_POST_invalid_embargo_end_date_returns_HTTPBad_Request( self, mock_enqueue): res = self.app.post(self.project.api_url_for( 'node_register_template_page_post', template=u'Open-Ended_Registration'), self.invalid_embargo_date_payload, content_type='application/json', auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 400) @mock.patch('framework.tasks.handlers.enqueue_task') def test_valid_POST_embargo_adds_to_parent_projects_log( self, mock_enquque): initial_project_logs = len(self.project.logs) res = self.app.post(self.project.api_url_for( 'node_register_template_page_post', template=u'Open-Ended_Registration'), self.valid_embargo_payload, content_type='application/json', auth=self.user.auth) self.project.reload() # Logs: Created, registered, embargo initiated assert_equal(len(self.project.logs), initial_project_logs + 1) def test_non_contributor_GET_approval_returns_HTTPError(self): non_contributor = AuthUserFactory() self.registration.embargo_registration( self.user, datetime.datetime.utcnow() + datetime.timedelta(days=10)) self.registration.save() assert_true(self.registration.is_pending_embargo) approval_token = self.registration.embargo.approval_state[ self.user._id]['approval_token'] approval_url = self.registration.web_url_for('view_project', token=approval_token) res = self.app.get(approval_url, auth=non_contributor.auth, expect_errors=True) assert_equal(http.FORBIDDEN, res.status_code) assert_true(self.registration.is_pending_embargo) assert_false(self.registration.embargo_end_date) def test_non_contributor_GET_disapproval_returns_HTTPError(self): non_contributor = AuthUserFactory() self.registration.embargo_registration( self.user, datetime.datetime.utcnow() + datetime.timedelta(days=10)) self.registration.save() assert_true(self.registration.is_pending_embargo) rejection_token = self.registration.embargo.approval_state[ self.user._id]['rejection_token'] approval_url = self.registration.web_url_for('view_project', token=rejection_token) res = self.app.get(approval_url, auth=non_contributor.auth, expect_errors=True) assert_equal(http.FORBIDDEN, res.status_code) assert_true(self.registration.is_pending_embargo) assert_false(self.registration.embargo_end_date)
class TestAddonLogs(OsfTestCase): def setUp(self): super(TestAddonLogs, self).setUp() self.flask_app = SetEnvironMiddleware(self.app.app, REMOTE_ADDR='127.0.0.1') self.test_app = webtest.TestApp(self.flask_app) self.user = AuthUserFactory() self.auth_obj = Auth(user=self.user) self.node = ProjectFactory(creator=self.user) self.session = Session(data={'auth_user_id': self.user._id}) self.session.save() self.cookie = itsdangerous.Signer(settings.SECRET_KEY).sign( self.session._id) self.configure_addon() def configure_addon(self): self.user.add_addon('github') self.user_addon = self.user.get_addon('github') self.oauth_settings = AddonGitHubOauthSettings(github_user_id='john') self.oauth_settings.save() self.user_addon.oauth_settings = self.oauth_settings self.user_addon.oauth_access_token = 'secret' self.user_addon.save() self.node.add_addon('github', self.auth_obj) self.node_addon = self.node.get_addon('github') self.node_addon.user = '******' self.node_addon.repo = 'youre-my-best-friend' self.node_addon.user_settings = self.user_addon self.node_addon.save() def build_payload(self, metadata, **kwargs): options = dict( auth={'id': self.user._id}, action='create', provider=self.node_addon.config.short_name, metadata=metadata, time=time.time() + 1000, ) options.update(kwargs) options = { key: value for key, value in options.iteritems() if value is not None } message, signature = signing.default_signer.sign_payload(options) return { 'payload': message, 'signature': signature, } @mock.patch('website.notifications.events.files.FileAdded.perform') def test_add_log(self, mock_perform): path = 'pizza' url = self.node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}) nlogs = len(self.node.logs) self.test_app.put_json(url, payload, headers={'Content-Type': 'application/json'}) self.node.reload() assert_equal(len(self.node.logs), nlogs + 1) # # Mocking form_message and perform so that the payload need not be exact. # assert_true(mock_form_message.called, "form_message not called") assert_true(mock_perform.called, "perform not called") def test_add_log_missing_args(self): path = 'pizza' url = self.node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}, auth=None) nlogs = len(self.node.logs) res = self.test_app.put_json( url, payload, headers={'Content-Type': 'application/json'}, expect_errors=True, ) assert_equal(res.status_code, 400) self.node.reload() assert_equal(len(self.node.logs), nlogs) def test_add_log_no_user(self): path = 'pizza' url = self.node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}, auth={'id': None}) nlogs = len(self.node.logs) res = self.test_app.put_json( url, payload, headers={'Content-Type': 'application/json'}, expect_errors=True, ) assert_equal(res.status_code, 400) self.node.reload() assert_equal(len(self.node.logs), nlogs) def test_add_log_no_addon(self): path = 'pizza' node = ProjectFactory(creator=self.user) url = node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}) nlogs = len(node.logs) res = self.test_app.put_json( url, payload, headers={'Content-Type': 'application/json'}, expect_errors=True, ) assert_equal(res.status_code, 400) self.node.reload() assert_equal(len(node.logs), nlogs) def test_add_log_bad_action(self): path = 'pizza' url = self.node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}, action='dance') nlogs = len(self.node.logs) res = self.test_app.put_json( url, payload, headers={'Content-Type': 'application/json'}, expect_errors=True, ) assert_equal(res.status_code, 400) self.node.reload() assert_equal(len(self.node.logs), nlogs) def test_action_file_rename(self): url = self.node.api_url_for('create_waterbutler_log') payload = self.build_payload( action='rename', metadata={ 'path': 'foo', }, source={ 'materialized': 'foo', 'provider': 'github', 'node': { '_id': self.node._id }, 'name': 'new.txt', 'kind': 'file', }, destination={ 'path': 'foo', 'materialized': 'foo', 'provider': 'github', 'node': { '_id': self.node._id }, 'name': 'old.txt', 'kind': 'file', }, ) self.test_app.put_json(url, payload, headers={'Content-Type': 'application/json'}) self.node.reload() assert_equal( self.node.logs[-1].action, 'github_addon_file_renamed', )
class TestWikiRename(OsfTestCase): def setUp(self): super(TestWikiRename, self).setUp() self.project = ProjectFactory(is_public=True) api_key = ApiKeyFactory() self.project.creator.api_keys.append(api_key) self.project.creator.save() self.consolidate_auth = Auth(user=self.project.creator, api_key=api_key) self.auth = ('test', api_key._primary_key) self.project.update_node_wiki('home', 'Hello world', self.consolidate_auth) self.page_name = 'page2' self.project.update_node_wiki(self.page_name, 'content', self.consolidate_auth) self.project.save() self.page = self.project.get_wiki_page(self.page_name) self.wiki = self.project.get_wiki_page('home') self.url = self.project.api_url_for( 'project_wiki_rename', wname=self.page_name, ) def test_rename_wiki_page_valid(self, new_name=u'away'): self.app.put_json(self.url, {'value': new_name}, auth=self.auth) self.project.reload() old_wiki = self.project.get_wiki_page(self.page_name) assert_false(old_wiki) new_wiki = self.project.get_wiki_page(new_name) assert_true(new_wiki) assert_equal(new_wiki._primary_key, self.page._primary_key) assert_equal(new_wiki.content, self.page.content) assert_equal(new_wiki.version, self.page.version) def test_rename_wiki_page_invalid(self, new_name=u'invalid/name'): res = self.app.put_json( self.url, {'value': new_name}, auth=self.auth, expect_errors=True, ) assert_equal(http.BAD_REQUEST, res.status_code) assert_equal(res.json['message_short'], 'Invalid name') assert_equal(res.json['message_long'], 'Page name cannot contain forward slashes.') self.project.reload() old_wiki = self.project.get_wiki_page(self.page_name) assert_true(old_wiki) def test_rename_wiki_page_duplicate(self): self.project.update_node_wiki('away', 'Hello world', self.consolidate_auth) new_name = 'away' res = self.app.put_json( self.url, {'value': new_name}, auth=self.auth, expect_errors=True, ) assert_equal(res.status_code, 409) def test_rename_wiki_name_not_found(self): url = self.project.api_url_for('project_wiki_rename', wname='not_found_page_name') res = self.app.put_json(url, {'value': 'new name'}, auth=self.auth, expect_errors=True) assert_equal(res.status_code, 404) def test_cannot_rename_wiki_page_to_home(self): user = AuthUserFactory() # A fresh project where the 'home' wiki page has no content project = ProjectFactory(creator=user) project.update_node_wiki('Hello', 'hello world', Auth(user=user)) url = project.api_url_for('project_wiki_rename', wname=to_mongo_key('Hello')) res = self.app.put_json(url, {'value': 'home'}, auth=user.auth, expect_errors=True) assert_equal(res.status_code, 409) def test_rename_wiki_name_with_value_missing(self): # value is missing res = self.app.put_json(self.url, {}, auth=self.auth, expect_errors=True) assert_equal(res.status_code, 400) def test_rename_wiki_page_duplicate_different_casing(self): # attempt to rename 'page2' from setup to different case of 'away'. old_name = 'away' new_name = 'AwAy' self.project.update_node_wiki(old_name, 'Hello world', self.consolidate_auth) res = self.app.put_json(self.url, {'value': new_name}, auth=self.auth, expect_errors=True) assert_equal(res.status_code, 409) def test_rename_wiki_page_same_name_different_casing(self): old_name = 'away' new_name = 'AWAY' self.project.update_node_wiki(old_name, 'Hello world', self.consolidate_auth) url = self.project.api_url_for('project_wiki_rename', wname=old_name) res = self.app.put_json(url, {'value': new_name}, auth=self.auth, expect_errors=False) assert_equal(res.status_code, 200) def test_cannot_rename_home_page(self): url = self.project.api_url_for('project_wiki_rename', wname='home') res = self.app.put_json(url, {'value': 'homelol'}, auth=self.auth, expect_errors=True) assert_equal(res.status_code, 400) def test_can_rename_to_a_deleted_page(self): self.project.delete_node_wiki(self.page_name, self.consolidate_auth) self.project.save() # Creates a new page self.project.update_node_wiki('page3', 'moarcontent', self.consolidate_auth) self.project.save() # Renames the wiki to the deleted page url = self.project.api_url_for('project_wiki_rename', wname='page3') res = self.app.put_json(url, {'value': self.page_name}, auth=self.auth) assert_equal(res.status_code, 200) def test_rename_wiki_page_with_valid_html(self): # script is not an issue since data is sanitized via bleach or mako before display. self.test_rename_wiki_page_valid(new_name=u'<html>hello<html>') def test_rename_wiki_page_with_invalid_html(self): # script is not an issue since data is sanitized via bleach or mako before display. # with that said routes still do not accept forward slashes self.test_rename_wiki_page_invalid(new_name=u'<html>hello</html>') def test_rename_wiki_page_with_non_ascii_title(self): self.test_rename_wiki_page_valid(new_name=u'øˆ∆´ƒøßå√ß') def test_rename_wiki_page_with_valid_special_character_title(self): self.test_rename_wiki_page_valid(new_name=SPECIAL_CHARACTERS_ALLOWED) def test_rename_wiki_page_with_invalid_special_character_title(self): self.test_rename_wiki_page_invalid(new_name=SPECIAL_CHARACTERS_ALL)
class TestS3ViewsConfig(OsfTestCase): def setUp(self): super(TestS3ViewsConfig, self).setUp() self.patcher = mock.patch('website.addons.s3.model.AddonS3UserSettings.is_valid', new=True) self.patcher.start() self.user = AuthUserFactory() self.consolidated_auth = Auth(user=self.user) self.auth = self.user.auth self.project = ProjectFactory(creator=self.user) self.project.add_addon('s3', auth=self.consolidated_auth) self.project.creator.add_addon('s3') self.user_settings = self.user.get_addon('s3') self.user_settings.access_key = 'We-Will-Rock-You' self.user_settings.secret_key = 'Idontknowanyqueensongs' self.user_settings.save() self.node_settings = self.project.get_addon('s3') self.node_settings.bucket = 'Sheer-Heart-Attack' self.node_settings.user_settings = self.project.creator.get_addon('s3') self.node_settings.save() self.node_url = '/api/v1/project/{0}/'.format(self.project._id) def tearDown(self): super(TestS3ViewsConfig, self).tearDown() self.patcher.stop() def test_s3_settings_input_empty_keys(self): url = self.project.api_url_for('s3_post_user_settings') rv = self.app.post_json(url,{ 'access_key': '', 'secret_key': '' }, auth=self.user.auth, expect_errors=True) assert_equals(rv.status_int, http.BAD_REQUEST) assert_in('All the fields above are required.', rv.body) def test_s3_settings_input_empty_access_key(self): url = self.project.api_url_for('s3_post_user_settings') rv = self.app.post_json(url,{ 'access_key': '', 'secret_key': 'Non-empty-secret-key' }, auth=self.user.auth, expect_errors=True) assert_equals(rv.status_int, http.BAD_REQUEST) assert_in('All the fields above are required.', rv.body) def test_s3_settings_input_empty_secret_key(self): url = self.project.api_url_for('s3_post_user_settings') rv = self.app.post_json(url,{ 'access_key': 'Non-empty-access-key', 'secret_key': '' }, auth=self.user.auth, expect_errors=True) assert_equals(rv.status_int, http.BAD_REQUEST) assert_in('All the fields above are required.', rv.body) def test_s3_settings_no_bucket(self): rv = self.app.post_json( self.project.api_url_for('s3_post_node_settings'), {}, expect_errors=True, auth=self.user.auth ) assert_in('trouble', rv.body) @mock.patch('website.addons.s3.views.config.utils.bucket_exists') def test_s3_set_bucket(self, mock_exists): mock_exists.return_value = True url = self.project.api_url_for('s3_post_node_settings') self.app.post_json( url, {'s3_bucket': 'hammertofall'}, auth=self.user.auth, ) self.project.reload() self.node_settings.reload() assert_equal(self.node_settings.bucket, 'hammertofall') assert_equal(self.project.logs[-1].action, 's3_bucket_linked') def test_s3_set_bucket_no_settings(self): user = AuthUserFactory() self.project.add_contributor(user, save=True) url = self.project.api_url_for('s3_post_node_settings') res = self.app.post_json( url, {'s3_bucket': 'hammertofall'}, auth=user.auth, expect_errors=True ) assert_equal(res.status_code, http.BAD_REQUEST) def test_s3_set_bucket_no_auth(self): user = AuthUserFactory() user.add_addon('s3') self.project.add_contributor(user, save=True) url = self.project.api_url_for('s3_post_node_settings') res = self.app.post_json( url, {'s3_bucket': 'hammertofall'}, auth=user.auth, expect_errors=True ) assert_equal(res.status_code, http.BAD_REQUEST) def test_s3_set_bucket_already_authed(self): user = AuthUserFactory() user.add_addon('s3') user_settings = user.get_addon('s3') user_settings.access_key = 'foo' user_settings.secret_key = 'bar' user_settings.save() self.project.add_contributor(user, save=True) url = self.project.api_url_for('s3_post_node_settings') res = self.app.post_json( url, {'s3_bucket': 'hammertofall'}, auth=user.auth, expect_errors=True ) assert_equal(res.status_code, http.BAD_REQUEST) def test_s3_set_bucket_registered(self): registration = self.project.register_node( None, self.consolidated_auth, '', '' ) url = registration.api_url_for('s3_post_node_settings') res = self.app.post_json( url, {'s3_bucket': 'hammertofall'}, auth=self.user.auth, expect_errors=True, ) assert_equal(res.status_code, http.BAD_REQUEST) @mock.patch('website.addons.s3.views.config.utils.can_list', return_value=True) def test_user_settings(self, _): url = self.project.api_url_for('s3_post_user_settings') self.app.post_json( url, { 'access_key': 'Steven Hawking', 'secret_key': 'Atticus Fitch killing mocking' }, auth=self.user.auth ) self.user_settings.reload() assert_equals(self.user_settings.access_key, 'Steven Hawking') assert_equals(self.user_settings.secret_key, 'Atticus Fitch killing mocking') @mock.patch('website.addons.s3.views.config.utils.can_list', return_value=True) def test_user_settings_when_user_does_not_have_addon(self, _): user = AuthUserFactory() url = self.project.api_url_for('s3_post_user_settings') self.app.post_json( url, { 'access_key': 'ABCDEFG', 'secret_key': 'We are the champions' }, auth=user.auth ) user.reload() user_settings = user.get_addon('s3') assert_equals(user_settings.access_key, 'ABCDEFG') assert_equals(user_settings.secret_key, 'We are the champions') def test_s3_remove_user_settings(self): self.user_settings.access_key = 'to-kill-a-mocking-bucket' self.user_settings.secret_key = 'itsasecret' self.user_settings.save() url = api_url_for('s3_delete_user_settings') self.app.delete(url, auth=self.user.auth) self.user_settings.reload() assert_equals(self.user_settings.access_key, None) assert_equals(self.user_settings.secret_key, None) # Last log has correct action and user self.project.reload() last_project_log = self.project.logs[-1] assert_equal(last_project_log.action, 's3_node_deauthorized') assert_equal(last_project_log.user, self.user) def test_s3_remove_user_settings_none(self): self.user_settings.access_key = None self.user_settings.secret_key = None self.user_settings.save() url = api_url_for('s3_delete_user_settings') self.app.delete(url, auth=self.user.auth) self.user_settings.reload() @mock.patch('website.addons.s3.views.config.utils.can_list', return_value=False) def test_user_settings_cant_list(self, mock_can_list): url = api_url_for('s3_post_user_settings') rv = self.app.post_json(url, { 'access_key': 'aldkjf', 'secret_key': 'las' }, auth=self.user.auth, expect_errors=True) assert_equals(rv.status_int, http.BAD_REQUEST) assert_in('Unable to list buckets.', rv.body) @mock.patch('website.addons.s3.views.config.utils.can_list', return_value=True) def test_node_settings_no_user_settings(self, mock_can_list): self.node_settings.user_settings = None self.node_settings.save() url = self.project.api_url_for('s3_authorize_node') self.app.post_json(url, {'access_key': 'scout', 'secret_key': 'ssshhhhhhhhh'}, auth=self.user.auth) self.user_settings.reload() assert_equals(self.user_settings.access_key, 'scout') @mock.patch('website.addons.s3.views.config.utils.get_bucket_names') def test_s3_bucket_list(self, mock_bucket_list): fake_buckets = [] for _ in range(10): fake_bucket = mock.Mock() fake_bucket.name = fake.domain_word() fake_bucket.append(fake_bucket) mock_bucket_list.return_value = fake_buckets url = self.node_settings.owner.api_url_for('s3_get_bucket_list') ret = self.app.get(url, auth=self.user.auth) assert_equals(ret.json, {'buckets': [bucket.name for bucket in fake_buckets]}) def test_s3_remove_node_settings_owner(self): url = self.node_settings.owner.api_url_for('s3_delete_node_settings') ret = self.app.delete(url, auth=self.user.auth) assert_equal(ret.json['has_bucket'], False) assert_equal(ret.json['node_has_auth'], False) def test_s3_remove_node_settings_unauthorized(self): url = self.node_settings.owner.api_url_for('s3_delete_node_settings') ret = self.app.delete(url, auth=None, expect_errors=True) assert_equal(ret.status_code, 401) def test_s3_get_node_settings_owner(self): url = self.node_settings.owner.api_url_for('s3_get_node_settings') res = self.app.get(url, auth=self.user.auth) result = res.json['result'] assert_equal(result['node_has_auth'], True) assert_equal(result['user_is_owner'], True) assert_equal(result['bucket'], self.node_settings.bucket) def test_s3_get_node_settings_not_owner(self): url = self.node_settings.owner.api_url_for('s3_get_node_settings') non_owner = AuthUserFactory() self.project.add_contributor(non_owner, save=True, permissions=['write']) res = self.app.get(url, auth=non_owner.auth) result = res.json['result'] assert_equal(result['bucket'], self.node_settings.bucket) assert_equal(result['node_has_auth'], True) assert_equal(result['user_is_owner'], False) def test_s3_get_node_settings_unauthorized(self): url = self.node_settings.owner.api_url_for('s3_get_node_settings') unauthorized = AuthUserFactory() ret = self.app.get(url, auth=unauthorized.auth, expect_errors=True) assert_equal(ret.status_code, 403) @mock.patch('website.addons.s3.views.config.utils.can_list', return_value=True) def test_s3_authorize_node_valid(self, _): url = self.project.api_url_for('s3_authorize_node') cred = { 'access_key': fake.password(), 'secret_key': fake.password(), } res = self.app.post_json(url, cred, auth=self.user.auth) assert_equal(res.json['node_has_auth'], True) def test_s3_authorize_node_malformed(self): url = self.project.api_url_for('s3_authorize_node') cred = { 'access_key': fake.password(), } res = self.app.post_json(url, cred, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 400) @mock.patch('website.addons.s3.views.config.utils.can_list', return_value=False) def test_s3_authorize_node_invalid(self, _): url = self.project.api_url_for('s3_authorize_node') cred = { 'access_key': fake.password(), 'secret_key': fake.password(), } res = self.app.post_json(url, cred, auth=self.user.auth, expect_errors=True) assert_in('Unable to list buckets', res.json['message']) assert_equal(res.status_code, 400) def test_s3_authorize_node_unauthorized(self): url = self.project.api_url_for('s3_authorize_node') cred = { 'access_key': fake.password(), 'secret_key': fake.password(), } unauthorized = AuthUserFactory() res = self.app.post_json(url, cred, auth=unauthorized.auth, expect_errors=True) assert_equal(res.status_code, 403) @mock.patch('website.addons.s3.views.config.utils.can_list', return_value=True) def test_s3_authorize_user_valid(self, _): url = self.project.api_url_for('s3_authorize_node') cred = { 'access_key': fake.password(), 'secret_key': fake.password(), } res = self.app.post_json(url, cred, auth=self.user.auth) assert_equal(res.status_code, 200) def test_s3_authorize_user_malformed(self): url = self.project.api_url_for('s3_authorize_node') cred = { 'access_key': fake.password(), } res = self.app.post_json(url, cred, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 400) @mock.patch('website.addons.s3.views.config.utils.can_list', return_value=False) def test_s3_authorize_user_invalid(self, _): url = self.project.api_url_for('s3_authorize_node') cred = { 'access_key': fake.password(), 'secret_key': fake.password(), } res = self.app.post_json(url, cred, auth=self.user.auth, expect_errors=True) assert_in('Unable to list buckets', res.json['message']) assert_equal(res.status_code, 400) def test_s3_authorize_input_empty_keys(self): url = self.project.api_url_for('s3_authorize_node') cred = { 'access_key': '', 'secret_key': '', } res = self.app.post_json(url, cred, auth=self.user.auth, expect_errors=True) assert_in('All the fields above are required', res.json['message']) assert_equal(res.status_code, 400) def test_s3_authorize_input_empty_access_key(self): url = self.project.api_url_for('s3_authorize_node') cred = { 'access_key': '', 'secret_key': 'Non-empty-secret-key', } res = self.app.post_json(url, cred, auth=self.user.auth, expect_errors=True) assert_in('All the fields above are required', res.json['message']) assert_equal(res.status_code, 400) def test_s3_authorize_input_empty_secret_key(self): url = self.project.api_url_for('s3_authorize_node') cred = { 'access_key': 'Non-empty-access-key', 'secret_key': '', } res = self.app.post_json(url, cred, auth=self.user.auth, expect_errors=True) assert_in('All the fields above are required', res.json['message']) assert_equal(res.status_code, 400) @mock.patch('website.addons.s3.views.config.utils.can_list', return_value=True) def test_s3_node_import_auth_authorized(self, _): url = self.project.api_url_for('s3_node_import_auth') self.node_settings.deauthorize(auth=None, save=True) res = self.app.post(url, auth=self.user.auth) assert_equal(res.json['node_has_auth'], True) assert_equal(res.json['user_is_owner'], True) def test_s3_node_import_auth_unauthorized(self): url = self.project.api_url_for('s3_node_import_auth') self.node_settings.deauthorize(auth=None, save=True) unauthorized = AuthUserFactory() res = self.app.post(url, auth=unauthorized.auth, expect_errors=True) assert_equal(res.status_code, 403)
class TestAddonAuth(OsfTestCase): def setUp(self): super(TestAddonAuth, self).setUp() self.flask_app = SetEnvironMiddleware(self.app.app, REMOTE_ADDR='127.0.0.1') self.test_app = webtest.TestApp(self.flask_app) self.user = AuthUserFactory() self.auth_obj = Auth(user=self.user) self.node = ProjectFactory(creator=self.user) self.session = Session(data={'auth_user_id': self.user._id}) self.session.save() self.cookie = itsdangerous.Signer(settings.SECRET_KEY).sign(self.session._id) self.configure_addon() def configure_addon(self): self.user.add_addon('github') self.user_addon = self.user.get_addon('github') self.oauth_settings = AddonGitHubOauthSettings(github_user_id='john') self.oauth_settings.save() self.user_addon.oauth_settings = self.oauth_settings self.user_addon.oauth_access_token = 'secret' self.user_addon.save() self.node.add_addon('github', self.auth_obj) self.node_addon = self.node.get_addon('github') self.node_addon.user = '******' self.node_addon.repo = 'youre-my-best-friend' self.node_addon.user_settings = self.user_addon self.node_addon.save() def build_url(self, **kwargs): options = dict( action='download', cookie=self.cookie, nid=self.node._id, provider=self.node_addon.config.short_name, ) options.update(kwargs) return api_url_for('get_auth', **options) def test_auth_download(self): url = self.build_url() res = self.test_app.get(url) assert_equal(res.json['auth'], views.make_auth(self.user)) assert_equal(res.json['credentials'], self.node_addon.serialize_waterbutler_credentials()) assert_equal(res.json['settings'], self.node_addon.serialize_waterbutler_settings()) expected_url = furl.furl(self.node.api_url_for('create_waterbutler_log', _absolute=True)) observed_url = furl.furl(res.json['callback_url']) observed_url.port = expected_url.port assert_equal(expected_url, observed_url) def test_auth_missing_args(self): url = self.build_url(cookie=None) res = self.test_app.get(url, expect_errors=True) assert_equal(res.status_code, 401) def test_auth_bad_cookie(self): url = self.build_url(cookie=self.cookie[::-1]) res = self.test_app.get(url, expect_errors=True) assert_equal(res.status_code, 401) def test_auth_missing_addon(self): url = self.build_url(provider='queenhub') res = self.test_app.get(url, expect_errors=True) assert_equal(res.status_code, 400) def test_auth_bad_ip(self): flask_app = SetEnvironMiddleware(self.app.app, REMOTE_ADDR='192.168.1.1') test_app = webtest.TestApp(flask_app) url = self.build_url() res = test_app.get(url, expect_errors=True) assert_equal(res.status_code, 403)
class MendeleyViewsTestCase(OsfTestCase): def setUp(self): super(MendeleyViewsTestCase, self).setUp() self.account = MendeleyAccountFactory() self.user = AuthUserFactory(external_accounts=[self.account]) self.account.display_name = self.user.fullname self.account.save() self.user_addon = MendeleyUserSettingsFactory(owner=self.user, external_account=self.account) self.project = ProjectFactory(creator=self.user) self.node_addon = MendeleyNodeSettingsFactory(owner=self.project) self.node_addon.set_auth(external_account=self.account, user=self.user) #self.user_addon.grant_oauth_access(self.node_addon, self.account, metadata={'lists': 'list'}) self.node = MockNode() self.node.addon = self.node_addon self.id_patcher = mock.patch('website.addons.mendeley.model.Mendeley.client_id') self.secret_patcher = mock.patch('website.addons.mendeley.model.Mendeley.client_secret') self.id_patcher.__get__ = mock.Mock(return_value='1234567890asdf') self.secret_patcher.__get__ = mock.Mock(return_value='1234567890asdf') self.id_patcher.start() self.secret_patcher.start() def tearDown(self): self.id_patcher.stop() self.secret_patcher.stop() def test_serialize_settings_authorizer(self): #"""dict: a serialized version of user-specific addon settings""" res = self.app.get( self.project.api_url_for('mendeley_get_config'), auth=self.user.auth, ) result = res.json['result'] assert_true(result['nodeHasAuth']) assert_true(result['userHasAuth']) assert_true(result['userIsOwner']) assert_equal(result['folder'], {'name': ''}) assert_equal(result['ownerName'], self.user.fullname) assert_true(result['urls']['auth']) assert_true(result['urls']['config']) assert_true(result['urls']['deauthorize']) assert_true(result['urls']['folders']) assert_true(result['urls']['importAuth']) assert_true(result['urls']['settings']) def test_serialize_settings_non_authorizer(self): #"""dict: a serialized version of user-specific addon settings""" non_authorizing_user = AuthUserFactory() self.project.add_contributor(non_authorizing_user, save=True) res = self.app.get( self.project.api_url_for('mendeley_get_config'), auth=non_authorizing_user.auth, ) result = res.json['result'] assert_true(result['nodeHasAuth']) assert_false(result['userHasAuth']) assert_false(result['userIsOwner']) assert_equal(result['folder'], {'name': ''}) assert_equal(result['ownerName'], self.user.fullname) assert_true(result['urls']['auth']) assert_true(result['urls']['config']) assert_true(result['urls']['deauthorize']) assert_true(result['urls']['folders']) assert_true(result['urls']['importAuth']) assert_true(result['urls']['settings']) def test_set_auth(self): res = self.app.put_json( self.project.api_url_for('mendeley_add_user_auth'), { 'external_account_id': self.account._id, }, auth=self.user.auth, ) assert_equal( res.status_code, 200 ) assert_true(res.json['result']['userHasAuth']) assert_equal( self.node_addon.user_settings, self.user_addon ) assert_equal( self.node_addon.external_account, self.account ) def test_remove_user_auth(self): self.node_addon.set_auth(self.account, self.user) res = self.app.delete_json( self.project.api_url_for('mendeley_remove_user_auth'), { 'external_account_id': self.account._id, }, auth=self.user.auth, ) assert_equal( res.status_code, 200 ) self.node_addon.reload() assert_is_none(self.node_addon.user_settings) assert_is_none(self.node_addon.external_account) @mock.patch('website.addons.mendeley.model.Mendeley._folder_metadata') def test_set_config_owner(self, mock_metadata): mock_metadata.return_value = MockFolder(name='Fake Folder') # Settings config updates node settings self.node_addon.associated_user_settings = [] self.node_addon.save() res = self.app.put_json( self.project.api_url_for('mendeley_set_config'), { 'external_account_id': self.account._id, 'external_list_id': 'list', }, auth=self.user.auth, ) self.node_addon.reload() assert_equal(self.user_addon, self.node_addon.user_settings) serializer = MendeleySerializer(node_settings=self.node_addon, user_settings=self.user_addon) expected = { 'result': serializer.serialized_node_settings } assert_equal(res.json, expected) @mock.patch('website.addons.mendeley.model.Mendeley._folder_metadata') def test_set_config_not_owner(self, mock_metadata): mock_metadata.return_value = MockFolder(name='Fake Folder') user = AuthUserFactory() user.add_addon('mendeley') self.project.add_contributor(user) self.project.save() res = self.app.put_json( self.project.api_url_for('mendeley_set_config'), { 'external_account_id': self.account._id, 'external_list_id': 'list', }, auth=user.auth, ) self.node_addon.reload() assert_equal(self.user_addon, self.node_addon.user_settings) serializer = MendeleySerializer(node_settings=self.node_addon, user_settings=None) expected = { 'result': serializer.serialized_node_settings } assert_equal(res.json, expected) def test_mendeley_widget_view_complete(self): # JSON: everything a widget needs assert_false(self.node_addon.complete) assert_equal(self.node_addon.mendeley_list_id, None) self.node_addon.set_target_folder('ROOT-ID', 'ROOT', auth=Auth(user=self.user)) res = views.mendeley_widget(node_addon=self.node_addon, project=self.project, node=self.node, nid=self.node_addon._id, pid=self.project._id, auth=self.user.auth) assert_true(res['complete']) assert_equal(res['list_id'], 'ROOT-ID') def test_widget_view_incomplete(self): # JSON: tell the widget when it hasn't been configured assert_false(self.node_addon.complete) assert_equal(self.node_addon.mendeley_list_id, None) res = views.mendeley_widget(node_addon=self.node_addon, project=self.project, node=self.node, nid=self.node_addon._id, pid=self.project._id, auth=self.user.auth) assert_false(res['complete']) assert_is_none(res['list_id']) @httpretty.activate def test_mendeley_citation_list_root(self): httpretty.register_uri( httpretty.GET, urlparse.urljoin(API_URL, 'folders'), body=mock_responses['folders'], content_type='application/json' ) res = self.app.get( self.project.api_url_for('mendeley_citation_list'), auth=self.user.auth ) root = res.json['contents'][0] assert_equal(root['kind'], 'folder') assert_equal(root['id'], 'ROOT') assert_equal(root['parent_list_id'], '__') @httpretty.activate def test_mendeley_citation_list_non_root(self): httpretty.register_uri( httpretty.GET, urlparse.urljoin(API_URL, 'folders'), body=mock_responses['folders'], content_type='application/json' ) httpretty.register_uri( httpretty.GET, urlparse.urljoin(API_URL, 'documents'), body=mock_responses['documents'], content_type='application/json' ) res = self.app.get( self.project.api_url_for('mendeley_citation_list', mendeley_list_id='ROOT'), auth=self.user.auth ) children = res.json['contents'] assert_equal(len(children), 7) assert_equal(children[0]['kind'], 'folder') assert_equal(children[1]['kind'], 'file') assert_true(children[1].get('csl') is not None) @httpretty.activate def test_mendeley_citation_list_non_linked_or_child_non_authorizer(self): non_authorizing_user = AuthUserFactory() self.project.add_contributor(non_authorizing_user, save=True) self.node_addon.mendeley_list_id = 'e843da05-8818-47c2-8c37-41eebfc4fe3f' self.node_addon.save() httpretty.register_uri( httpretty.GET, urlparse.urljoin(API_URL, 'folders'), body=mock_responses['folders'], content_type='application/json' ) httpretty.register_uri( httpretty.GET, urlparse.urljoin(API_URL, 'documents'), body=mock_responses['documents'], content_type='application/json' ) res = self.app.get( self.project.api_url_for('mendeley_citation_list', mendeley_list_id='ROOT'), auth=non_authorizing_user.auth, expect_errors=True ) assert_equal(res.status_code, 403)
class TestAddonLogs(OsfTestCase): def setUp(self): super(TestAddonLogs, self).setUp() self.flask_app = SetEnvironMiddleware(self.app.app, REMOTE_ADDR='127.0.0.1') self.test_app = webtest.TestApp(self.flask_app) self.user = AuthUserFactory() self.auth_obj = Auth(user=self.user) self.node = ProjectFactory(creator=self.user) self.session = Session(data={'auth_user_id': self.user._id}) self.session.save() self.cookie = itsdangerous.Signer(settings.SECRET_KEY).sign(self.session._id) self.configure_addon() def configure_addon(self): self.user.add_addon('github') self.user_addon = self.user.get_addon('github') self.oauth_settings = AddonGitHubOauthSettings(github_user_id='john') self.oauth_settings.save() self.user_addon.oauth_settings = self.oauth_settings self.user_addon.oauth_access_token = 'secret' self.user_addon.save() self.node.add_addon('github', self.auth_obj) self.node_addon = self.node.get_addon('github') self.node_addon.user = '******' self.node_addon.repo = 'youre-my-best-friend' self.node_addon.user_settings = self.user_addon self.node_addon.save() def build_payload(self, metadata, **kwargs): options = dict( auth={'id': self.user._id}, action='create', provider=self.node_addon.config.short_name, metadata=metadata, time=time.time() + 1000, ) options.update(kwargs) options = { key: value for key, value in options.iteritems() if value is not None } message, signature = signing.default_signer.sign_payload(options) return { 'payload': message, 'signature': signature, } def test_add_log(self): path = 'pizza' url = self.node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}) nlogs = len(self.node.logs) self.test_app.put_json(url, payload, headers={'Content-Type': 'application/json'}) self.node.reload() assert_equal(len(self.node.logs), nlogs + 1) def test_add_log_missing_args(self): path = 'pizza' url = self.node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}, auth=None) nlogs = len(self.node.logs) res = self.test_app.put_json( url, payload, headers={'Content-Type': 'application/json'}, expect_errors=True, ) assert_equal(res.status_code, 400) self.node.reload() assert_equal(len(self.node.logs), nlogs) def test_add_log_no_user(self): path = 'pizza' url = self.node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}, auth={'id': None}) nlogs = len(self.node.logs) res = self.test_app.put_json( url, payload, headers={'Content-Type': 'application/json'}, expect_errors=True, ) assert_equal(res.status_code, 400) self.node.reload() assert_equal(len(self.node.logs), nlogs) def test_add_log_no_addon(self): path = 'pizza' node = ProjectFactory(creator=self.user) url = node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}) nlogs = len(node.logs) res = self.test_app.put_json( url, payload, headers={'Content-Type': 'application/json'}, expect_errors=True, ) assert_equal(res.status_code, 400) self.node.reload() assert_equal(len(node.logs), nlogs) def test_add_log_bad_action(self): path = 'pizza' url = self.node.api_url_for('create_waterbutler_log') payload = self.build_payload(metadata={'path': path}, action='dance') nlogs = len(self.node.logs) res = self.test_app.put_json( url, payload, headers={'Content-Type': 'application/json'}, expect_errors=True, ) assert_equal(res.status_code, 400) self.node.reload() assert_equal(len(self.node.logs), nlogs)
class TestAddonAuth(OsfTestCase): def setUp(self): super(TestAddonAuth, self).setUp() self.flask_app = SetEnvironMiddleware(self.app.app, REMOTE_ADDR='127.0.0.1') self.test_app = webtest.TestApp(self.flask_app) self.user = AuthUserFactory() self.auth_obj = Auth(user=self.user) self.node = ProjectFactory(creator=self.user) self.session = Session(data={'auth_user_id': self.user._id}) self.session.save() self.cookie = itsdangerous.Signer(settings.SECRET_KEY).sign(self.session._id) self.configure_addon() def configure_addon(self): self.user.add_addon('github') self.user_addon = self.user.get_addon('github') self.oauth_settings = AddonGitHubOauthSettings(github_user_id='john') self.oauth_settings.save() self.user_addon.oauth_settings = self.oauth_settings self.user_addon.oauth_access_token = 'secret' self.user_addon.save() self.node.add_addon('github', self.auth_obj) self.node_addon = self.node.get_addon('github') self.node_addon.user = '******' self.node_addon.repo = 'youre-my-best-friend' self.node_addon.user_settings = self.user_addon self.node_addon.save() def build_url(self, **kwargs): options = dict( action='download', cookie=self.cookie, nid=self.node._id, provider=self.node_addon.config.short_name, ) options.update(kwargs) return api_url_for('get_auth', **options) def test_auth_download(self): url = self.build_url() res = self.test_app.get(url) assert_equal(res.json['auth'], views.make_auth(self.user)) assert_equal(res.json['credentials'], self.node_addon.serialize_waterbutler_credentials()) assert_equal(res.json['settings'], self.node_addon.serialize_waterbutler_settings()) expected_url = furl.furl(self.node.api_url_for('create_waterbutler_log', _absolute=True)) observed_url = furl.furl(res.json['callback_url']) observed_url.port = expected_url.port assert_equal(expected_url, observed_url) def test_auth_missing_args(self): url = self.build_url(cookie=None) res = self.test_app.get(url, expect_errors=True) assert_equal(res.status_code, 400) def test_auth_bad_cookie(self): url = self.build_url(cookie=self.cookie[::-1]) res = self.test_app.get(url, expect_errors=True) assert_equal(res.status_code, 401) def test_auth_missing_addon(self): url = self.build_url(provider='queenhub') res = self.test_app.get(url, expect_errors=True) assert_equal(res.status_code, 400) def test_auth_bad_ip(self): flask_app = SetEnvironMiddleware(self.app.app, REMOTE_ADDR='192.168.1.1') test_app = webtest.TestApp(flask_app) url = self.build_url() res = test_app.get(url, expect_errors=True) assert_equal(res.status_code, 403)
class TestAddonFileViews(OsfTestCase): def setUp(self): super(TestAddonFileViews, self).setUp() self.user = AuthUserFactory() self.project = ProjectFactory(creator=self.user) self.user.add_addon('github') self.project.add_addon('github', auth=Auth(self.user)) self.user_addon = self.user.get_addon('github') self.node_addon = self.project.get_addon('github') self.oauth = AddonGitHubOauthSettings( github_user_id='denbarell', oauth_access_token='Truthy' ) self.oauth.save() self.user_addon.oauth_settings = self.oauth self.user_addon.save() self.node_addon.user_settings = self.user_addon self.node_addon.save() # self.node_addon.user_settings = 'Truthy' # setattr(self.node_addon, 'has_auth', True) def get_mako_return(self): ret = serialize_node(self.project, Auth(self.user), primary=True) ret.update({ 'extra': '', 'provider': '', 'rendered': '', 'file_path': '', 'files_url': '', 'file_name': '', 'render_url': '', }) ret.update(rubeus.collect_addon_assets(self.project)) return ret def test_redirects_to_guid(self): path = 'bigdata' guid, _ = self.node_addon.find_or_create_file_guid('/' + path) resp = self.app.get( self.project.web_url_for( 'addon_view_or_download_file', path=path, provider='github' ), auth=self.user.auth ) assert_equals(resp.status_code, 302) assert_equals(resp.headers['Location'], 'http://*****:*****@mock.patch('website.addons.base.request') def test_public_download_url_includes_view_only(self, mock_request): view_only = 'justworkplease' mock_request.args = { 'view_only': view_only } path = 'cloudfiles' guid, _ = self.node_addon.find_or_create_file_guid('/' + path) assert_in('view_only={}'.format(view_only), guid.public_download_url) @mock.patch('website.addons.base.views.addon_view_file') def test_action_view_calls_view_file(self, mock_view_file): self.user.reload() self.project.reload() path = 'cloudfiles' mock_view_file.return_value = self.get_mako_return() guid, _ = self.node_addon.find_or_create_file_guid('/' + path) self.app.get(guid.guid_url + '?action=view', auth=self.user.auth) args, kwargs = mock_view_file.call_args assert_equals(kwargs, {}) assert_equals(args[-1], {'action': 'view'}) assert_equals(args[1], self.project) assert_equals(args[0].user, self.user) assert_equals(args[2], self.node_addon) @mock.patch('website.addons.base.views.addon_view_file') def test_no_action_calls_view_file(self, mock_view_file): self.user.reload() self.project.reload() path = 'cloudfiles' mock_view_file.return_value = self.get_mako_return() guid, _ = self.node_addon.find_or_create_file_guid('/' + path) self.app.get(guid.guid_url, auth=self.user.auth) args, kwargs = mock_view_file.call_args assert_equals(kwargs, {}) assert_equals(args[-1], {}) assert_equals(args[1], self.project) assert_equals(args[0].user, self.user) assert_equals(args[2], self.node_addon) def test_download_create_guid(self): path = 'cloudfiles' self.app.get( self.project.web_url_for( 'addon_view_or_download_file', path=path, provider='github', action='download' ), auth=self.user.auth ) guid, created = self.node_addon.find_or_create_file_guid('/' + path) assert_true(guid) assert_false(created) assert_equals(guid.waterbutler_path, '/' + path) def test_unauthorized_addons_raise(self): path = 'cloudfiles' self.node_addon.user_settings = None self.node_addon.save() resp = self.app.get( self.project.web_url_for( 'addon_view_or_download_file', path=path, provider='github', action='download' ), auth=self.user.auth, expect_errors=True ) assert_equals(resp.status_code, 403) def test_head_returns_url(self): path = 'the little engine that couldnt' guid, _ = self.node_addon.find_or_create_file_guid('/' + path) download_url = furl.furl(guid.download_url) download_url.args['accept_url'] = 'false' resp = self.app.head(guid.guid_url, auth=self.user.auth) assert_urls_equal(resp.headers['Location'], download_url.url) def test_nonexistent_addons_raise(self): path = 'cloudfiles' self.project.delete_addon('github', Auth(self.user)) self.project.save() resp = self.app.get( self.project.api_url_for( 'addon_render_file', path=path, provider='github', action='download' ), auth=self.user.auth, expect_errors=True ) assert_equals(resp.status_code, 400) def test_unauth_addons_raise(self): path = 'cloudfiles' self.node_addon.user_settings = None self.node_addon.save() resp = self.app.get( self.project.api_url_for( 'addon_render_file', path=path, provider='github', action='download' ), auth=self.user.auth, expect_errors=True ) assert_equals(resp.status_code, 401) def test_unconfigured_addons_raise(self): path = 'cloudfiles' self.node_addon.repo = None self.node_addon.save() resp = self.app.get( self.project.api_url_for( 'addon_render_file', path=path, provider='github', action='download' ), auth=self.user.auth, expect_errors=True ) assert_equals(resp.status_code, 400)
class TestViewsConfig(OsfTestCase): def setUp(self): super(TestViewsConfig, self).setUp() self.user = AuthUserFactory() self.consolidated_auth = Auth(user=self.user) self.auth = ('test', self.user.api_keys[0]._primary_key) self.project = ProjectFactory(creator=self.user) self.non_authenticator = AuthUserFactory() self.project.add_contributor( contributor=self.non_authenticator, auth=Auth(self.project.creator), ) self.project.add_addon('figshare', auth=self.consolidated_auth) self.project.creator.add_addon('figshare') self.node_settings = self.project.get_addon('figshare') self.user_settings = self.project.creator.get_addon('figshare') self.user_settings.oauth_access_token = 'legittoken' self.user_settings.oauth_access_token_secret = 'legittoken' self.user_settings.save() self.node_settings.user_settings = self.user_settings self.node_settings.figshare_id = '123456' self.node_settings.figshare_type = 'project' self.node_settings.figshare_title = 'FIGSHARE_TITLE' self.node_settings.save() self.figshare = create_mock_figshare('test') def configure_responses(self): httpretty.register_uri( httpretty.GET, join_path(self.node_settings.api_url, 'articles'), body=dumps(self.figshare.articles.return_value) ) httpretty.register_uri( httpretty.GET, join_path(self.node_settings.api_url, 'articles', '902210'), body=dumps(self.figshare.article.return_value) ) @httpretty.activate def test_import_auth(self): self.configure_responses() """Testing figshare_import_user_auth to ensure that auth gets imported correctly""" settings = self.node_settings settings.user_settings = None settings.save() url = '/api/v1/project/{0}/figshare/config/import-auth/'.format(self.project._id) self.app.put(url, auth=self.user.auth) self.node_settings.reload() assert_is_not_none(settings.user_settings) def test_cancelled_oauth_request_from_user_settings_page_redirects_correctly(self): res = self.app.get(api_url_for('figshare_oauth_callback', uid=self.user._id), auth=self.user.auth) assert_equal(res.status_code, 302) assert_urls_equal(res.headers['location'], web_url_for('user_addons')) def test_cancelled_oauth_request_from_node_settings_page_redirects_correctly(self): res = self.app.get(api_url_for('figshare_oauth_callback', uid=self.user._id, nid=self.project._id), auth=self.user.auth) assert_equal(res.status_code, 302) assert_urls_equal(res.headers['location'], self.project.web_url_for('node_setting')) def test_deauthorize(self): """Testing figshare_deauthorize to ensure user auth gets removed from the node and that the AddonNodeSettings are cleared """ settings = self.node_settings url = '/api/v1/project/{0}/figshare/config/'.format(self.project._id) self.app.delete(url, auth=self.user.auth) self.node_settings.reload() assert_true(settings.user_settings is None) is_none = ( settings.figshare_id is None and settings.figshare_title is None and settings.figshare_type is None ) assert_true(is_none) def test_config_no_change(self): nlogs = len(self.project.logs) url = self.project.api_url_for('figshare_config_put') rv = self.app.put_json( url, { 'selected': { 'id': '123456', 'name': 'FIGSHARE_TITLE', 'type': 'project', }, }, auth=self.user.auth, ) self.project.reload() assert_equal(rv.status_int, http.OK) assert_equal(len(self.project.logs), nlogs) def test_config_change(self): nlogs = len(self.project.logs) url = self.project.api_url_for('figshare_config_put') rv = self.app.put_json( url, { 'selected': { 'id': 'project_9001', 'name': 'IchangedbecauseIcan', 'type': 'project' }, }, auth=self.user.auth, ) self.project.reload() self.node_settings.reload() assert_equal(rv.status_int, http.OK) assert_equal(self.node_settings.figshare_id, 'project_9001') assert_equal(self.node_settings.figshare_title, 'IchangedbecauseIcan') assert_equal(len(self.project.logs), nlogs + 1) assert_equal( self.project.logs[nlogs].action, 'figshare_content_linked' ) def test_config_change_invalid(self): nlogs = len(self.project.logs) url = self.project.api_url_for('figshare_config_put') rv = self.app.put_json( url, { 'selected': { 'type': 'project' }, }, auth=self.user.auth, expect_errors=True, ) self.project.reload() self.node_settings.reload() assert_equal(rv.status_int, http.BAD_REQUEST) assert_equal(len(self.project.logs), nlogs) def test_config_change_not_owner(self): user2 = AuthUserFactory() self.project.add_contributor(user2, save=True) nlogs = len(self.project.logs) url = self.project.api_url_for('figshare_config_put') res = self.app.put_json( url, {}, auth=user2.auth, expect_errors=True, ) self.project.reload() assert_equal(res.status_int, http.FORBIDDEN) assert_equal(nlogs, len(self.project.logs)) @httpretty.activate def test_serialize_settings_helper_returns_correct_auth_info(self): self.configure_responses() result = serialize_settings(self.node_settings, self.user, client=figshare_mock) assert_equal(result['nodeHasAuth'], self.node_settings.has_auth) assert_true(result['userHasAuth']) assert_true(result['userIsOwner']) @httpretty.activate def test_serialize_settings_for_user_no_auth(self): self.configure_responses() no_addon_user = AuthUserFactory() result = serialize_settings(self.node_settings, no_addon_user, client=figshare_mock) assert_false(result['userIsOwner']) assert_false(result['userHasAuth'])
class TestWikiViews(OsfTestCase): def setUp(self): super(TestWikiViews, self).setUp() self.user = AuthUserFactory() self.project = ProjectFactory(is_public=True, creator=self.user) self.consolidate_auth = Auth(user=self.project.creator) def test_wiki_url_get_returns_200(self): url = self.project.web_url_for('project_wiki_page', wname='home') res = self.app.get(url) assert_equal(res.status_code, 200) def test_wiki_url_for_pointer_returns_200(self): # TODO: explain how this tests a pointer project = ProjectFactory(is_public=True) self.project.add_pointer(project, Auth(self.project.creator), save=True) url = self.project.web_url_for('project_wiki_page', wname='home') res = self.app.get(url) assert_equal(res.status_code, 200) def test_wiki_content_returns_200(self): node = ProjectFactory(is_public=True) url = node.api_url_for('wiki_page_content', wname='somerandomid') res = self.app.get(url) assert_equal(res.status_code, 200) def test_wiki_url_for_component_returns_200(self): component = NodeFactory(project=self.project, is_public=True) url = component.web_url_for('project_wiki_page', wname='home') res = self.app.get(url) assert_equal(res.status_code, 200) def test_serialize_wiki_toc(self): project = ProjectFactory() auth = Auth(project.creator) NodeFactory(project=project, creator=project.creator) no_wiki = NodeFactory(project=project, creator=project.creator) project.save() serialized = _serialize_wiki_toc(project, auth=auth) assert_equal(len(serialized), 2) no_wiki.delete_addon('wiki', auth=auth) serialized = _serialize_wiki_toc(project, auth=auth) assert_equal(len(serialized), 1) def test_get_wiki_url_pointer_component(self): """Regression test for issues https://github.com/CenterForOpenScience/osf/issues/363 and https://github.com/CenterForOpenScience/openscienceframework.org/issues/574 """ user = UserFactory() pointed_node = NodeFactory(creator=user) project = ProjectFactory(creator=user) auth = Auth(user=user) project.add_pointer(pointed_node, auth=auth, save=True) serialized = _serialize_wiki_toc(project, auth) assert_equal( serialized[0]['url'], pointed_node.web_url_for('project_wiki_page', wname='home', _guid=True)) def test_project_wiki_edit_post(self): self.project.update_node_wiki('home', content='old content', auth=Auth(self.project.creator)) url = self.project.web_url_for('project_wiki_edit_post', wname='home') res = self.app.post(url, { 'content': 'new content' }, auth=self.user.auth).follow() assert_equal(res.status_code, 200) self.project.reload() # page was updated with new content new_wiki = self.project.get_wiki_page('home') assert_equal(new_wiki.content, 'new content') def test_project_wiki_edit_post_with_new_wname_and_no_content(self): page_name = fake.catch_phrase() old_wiki_page_count = NodeWikiPage.find().count() url = self.project.web_url_for('project_wiki_edit_post', wname=page_name) # User submits to edit form with no content res = self.app.post(url, {'content': ''}, auth=self.user.auth).follow() assert_equal(res.status_code, 200) new_wiki_page_count = NodeWikiPage.find().count() # A new wiki page was created in the db assert_equal(new_wiki_page_count, old_wiki_page_count + 1) # Node now has the new wiki page associated with it self.project.reload() new_page = self.project.get_wiki_page(page_name) assert_is_not_none(new_page) def test_project_wiki_edit_post_with_new_wname_and_content(self): page_name, page_content = fake.catch_phrase(), fake.bs() old_wiki_page_count = NodeWikiPage.find().count() url = self.project.web_url_for('project_wiki_edit_post', wname=page_name) # User submits to edit form with no content res = self.app.post(url, { 'content': page_content }, auth=self.user.auth).follow() assert_equal(res.status_code, 200) new_wiki_page_count = NodeWikiPage.find().count() # A new wiki page was created in the db assert_equal(new_wiki_page_count, old_wiki_page_count + 1) # Node now has the new wiki page associated with it self.project.reload() new_page = self.project.get_wiki_page(page_name) assert_is_not_none(new_page) # content was set assert_equal(new_page.content, page_content) def test_project_wiki_edit_post_with_non_ascii_title(self): # regression test for https://github.com/CenterForOpenScience/openscienceframework.org/issues/1040 # wname doesn't exist in the db, so it will be created new_wname = u'øˆ∆´ƒøßå√ß' url = self.project.web_url_for('project_wiki_edit_post', wname=new_wname) res = self.app.post(url, { 'content': 'new content' }, auth=self.user.auth).follow() assert_equal(res.status_code, 200) self.project.reload() wiki = self.project.get_wiki_page(new_wname) assert_equal(wiki.page_name, new_wname) # updating content should return correct url as well. res = self.app.post(url, { 'content': 'updated content' }, auth=self.user.auth).follow() assert_equal(res.status_code, 200) def test_project_wiki_edit_post_with_special_characters(self): new_wname = 'title: ' + SPECIAL_CHARACTERS_ALLOWED new_wiki_content = 'content: ' + SPECIAL_CHARACTERS_ALL url = self.project.web_url_for('project_wiki_edit_post', wname=new_wname) res = self.app.post(url, { 'content': new_wiki_content }, auth=self.user.auth).follow() assert_equal(res.status_code, 200) self.project.reload() wiki = self.project.get_wiki_page(new_wname) assert_equal(wiki.page_name, new_wname) assert_equal(wiki.content, new_wiki_content) assert_equal(res.status_code, 200) def test_wiki_edit_get_home(self): url = self.project.web_url_for('project_wiki_edit', wname='home') res = self.app.get(url, auth=self.user.auth) assert_equal(res.status_code, 200) def test_project_wiki_compare_returns_200(self): self.project.update_node_wiki('home', 'updated content', Auth(self.user)) self.project.save() url = self.project.web_url_for('project_wiki_compare', wname='home', wver=1) res = self.app.get(url, auth=self.user.auth) assert_equal(res.status_code, 200) def test_project_wiki_compare_with_invalid_wname(self): url = self.project.web_url_for('project_wiki_compare', wname='this-doesnt-exist', wver=1) res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 404) def test_wiki_page_creation_strips_whitespace(self): # Regression test for: # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1080 # wname has a trailing space url = self.project.web_url_for('project_wiki_edit', wname='cupcake ') res = self.app.post(url, { 'content': 'blah' }, auth=self.user.auth).follow() assert_equal(res.status_code, 200) self.project.reload() wiki = self.project.get_wiki_page('cupcake') assert_is_not_none(wiki) def test_wiki_validate_name(self): url = self.project.api_url_for('project_wiki_validate_name', wname='Capslock') res = self.app.get(url, auth=self.user.auth) assert_equal(res.status_code, 200) def test_wiki_validate_name_cannot_create_home(self): url = self.project.api_url_for('project_wiki_validate_name', wname='home') res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 409) def test_project_wiki_validate_name_mixed_casing(self): url = self.project.api_url_for('project_wiki_validate_name', wname='CaPsLoCk') res = self.app.get(url, auth=self.user.auth) assert_equal(res.status_code, 200) assert_not_in('capslock', self.project.wiki_pages_current) self.project.update_node_wiki('CaPsLoCk', 'hello', self.consolidate_auth) assert_in('capslock', self.project.wiki_pages_current) def test_project_wiki_validate_name_diplay_correct_capitalization(self): url = self.project.api_url_for('project_wiki_validate_name', wname='CaPsLoCk') res = self.app.get(url, auth=self.user.auth) assert_equal(res.status_code, 200) assert_in('CaPsLoCk', res) def test_project_wiki_validate_name_conflict_different_casing(self): url = self.project.api_url_for('project_wiki_validate_name', wname='CAPSLOCK') res = self.app.get(url, auth=self.user.auth) assert_equal(res.status_code, 200) self.project.update_node_wiki('CaPsLoCk', 'hello', self.consolidate_auth) assert_in('capslock', self.project.wiki_pages_current) url = self.project.api_url_for('project_wiki_validate_name', wname='capslock') res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 409) def test_project_dashboard_shows_no_wiki_content_text(self): # Regression test for: # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104 project = ProjectFactory(creator=self.user) url = project.web_url_for('view_project') res = self.app.get(url, auth=self.user.auth) assert_in('No wiki content', res) def test_project_dashboard_wiki_wname_get_shows_non_ascii_characters(self): # Regression test for: # https://github.com/CenterForOpenScience/openscienceframework.org/issues/1104 text = u'你好' self.project.update_node_wiki('home', text, Auth(self.user)) # can view wiki preview from project dashboard url = self.project.web_url_for('view_project') res = self.app.get(url, auth=self.user.auth) assert_in(text, res) def test_project_wiki_home_api_route(self): url = self.project.api_url_for('project_wiki_home') res = self.app.get(url, auth=self.user.auth) assert_equals(res.status_code, 302) # TODO: should this route exist? it redirects you to the web_url_for, not api_url_for. # page_url = self.project.api_url_for('project_wiki_page', wname='home') # assert_in(page_url, res.location) def test_project_wiki_home_web_route(self): page_url = self.project.web_url_for('project_wiki_page', wname='home', _guid=True) url = self.project.web_url_for('project_wiki_home') res = self.app.get(url, auth=self.user.auth) assert_equals(res.status_code, 302) assert_in(page_url, res.location) def test_wiki_id_url_get_returns_302_and_resolves(self): name = 'page by id' self.project.update_node_wiki(name, 'some content', Auth(self.project.creator)) page = self.project.get_wiki_page(name) page_url = self.project.web_url_for('project_wiki_page', wname=page.page_name, _guid=True) url = self.project.web_url_for('project_wiki_id_page', wid=page._primary_key, _guid=True) res = self.app.get(url) assert_equal(res.status_code, 302) assert_in(page_url, res.location) res = res.follow() assert_equal(res.status_code, 200) assert_in(page_url, res.request.url) def test_wiki_id_url_get_returns_404(self): url = self.project.web_url_for('project_wiki_id_page', wid='12345', _guid=True) res = self.app.get(url, expect_errors=True) assert_equal(res.status_code, 404) def test_home_is_capitalized_in_web_view(self): url = self.project.web_url_for('project_wiki_home', wid='home', _guid=True) res = self.app.get(url, auth=self.user.auth).follow(auth=self.user.auth) page_name_elem = res.html.find('span', {'id': 'pageName'}) assert_in('Home', page_name_elem.text)
class TestCreateBucket(S3AddonTestCase): def setUp(self): super(TestCreateBucket, self).setUp() self.user = AuthUserFactory() self.consolidated_auth = Auth(user=self.user) self.auth = self.user.auth self.project = ProjectFactory(creator=self.user) self.project.add_addon('s3', auth=self.consolidated_auth) self.project.creator.add_addon('s3') self.user_settings = self.user.get_addon('s3') self.user_settings.access_key = 'We-Will-Rock-You' self.user_settings.secret_key = 'Idontknowanyqueensongs' self.user_settings.save() self.node_settings = self.project.get_addon('s3') self.node_settings.bucket = 'Sheer-Heart-Attack' self.node_settings.user_settings = self.project.creator.get_addon('s3') self.node_settings.save() def test_bad_names(self): assert_false(validate_bucket_name('')) assert_false(validate_bucket_name('no')) assert_false(validate_bucket_name('a' * 64)) assert_false(validate_bucket_name(' leadingspace')) assert_false(validate_bucket_name('trailingspace ')) assert_false(validate_bucket_name('bogus naMe')) assert_false(validate_bucket_name('.cantstartwithp')) assert_false(validate_bucket_name('or.endwith.')) assert_false(validate_bucket_name('..nodoubles')) assert_false(validate_bucket_name('no_unders_in')) assert_false(validate_bucket_name('-leadinghyphen')) assert_false(validate_bucket_name('trailinghyphen-')) assert_false(validate_bucket_name('Mixedcase')) assert_false(validate_bucket_name('empty..label')) assert_false(validate_bucket_name('label-.trailinghyphen')) assert_false(validate_bucket_name('label.-leadinghyphen')) assert_false(validate_bucket_name('8.8.8.8')) assert_false(validate_bucket_name('600.9000.0.28')) assert_false(validate_bucket_name('no_underscore')) assert_false(validate_bucket_name('_nounderscoreinfront')) assert_false(validate_bucket_name('no-underscore-in-back_')) assert_false( validate_bucket_name('no-underscore-in_the_middle_either')) def test_names(self): assert_true(validate_bucket_name('imagoodname')) assert_true(validate_bucket_name('still.passing')) assert_true(validate_bucket_name('can-have-dashes')) assert_true(validate_bucket_name('kinda.name.spaced')) assert_true(validate_bucket_name('a-o.valid')) assert_true(validate_bucket_name('11.12.m')) assert_true(validate_bucket_name('a--------a')) assert_true(validate_bucket_name('a' * 63)) def test_bad_locations(self): assert_false(validate_bucket_location('Venus')) assert_false(validate_bucket_location('AlphaCentari')) assert_false(validate_bucket_location('CostaRica')) def test_locations(self): assert_true(validate_bucket_location('')) assert_true(validate_bucket_location('us-east-2')) assert_true(validate_bucket_location('eu-central-1')) assert_true(validate_bucket_location('us-west-1')) assert_true(validate_bucket_location('us-west-2')) assert_true(validate_bucket_location('ap-northeast-1')) assert_true(validate_bucket_location('ap-northeast-2')) assert_true(validate_bucket_location('ap-southeast-1')) assert_true(validate_bucket_location('ap-southeast-2')) assert_true(validate_bucket_location('ap-south-1')) assert_true(validate_bucket_location('sa-east-1')) assert_true(validate_bucket_location('eu-west-1')) @mock.patch('website.addons.s3.views.utils.create_bucket') @mock.patch('website.addons.s3.views.utils.get_bucket_names') def test_create_bucket_pass(self, mock_names, mock_make): mock_make.return_value = True mock_names.return_value = ['butintheend', 'it', 'doesntevenmatter'] url = self.project.api_url_for('create_bucket') ret = self.app.post_json(url, { 'bucket_name': 'doesntevenmatter', 'bucket_location': '', }, auth=self.user.auth) assert_equal(ret.status_int, http.OK) assert_equal(ret.json, {}) @mock.patch('website.addons.s3.views.utils.create_bucket') def test_create_bucket_fail(self, mock_make): error = S3ResponseError(418, 'because Im a test') error.message = 'This should work' mock_make.side_effect = error url = "/api/v1/project/{0}/s3/newbucket/".format(self.project._id) ret = self.app.post_json(url, {'bucket_name': 'doesntevenmatter'}, auth=self.user.auth, expect_errors=True) assert_equals( ret.body, '{"message": "This should work", "title": "Problem connecting to S3"}' ) @mock.patch('website.addons.s3.views.utils.create_bucket') def test_bad_location_fails(self, mock_make): url = "/api/v1/project/{0}/s3/newbucket/".format(self.project._id) ret = self.app.post_json( url, { 'bucket_name': 'doesntevenmatter', 'bucket_location': 'not a real bucket location', }, auth=self.user.auth, expect_errors=True) assert_equals( ret.body, '{"message": "That bucket location is not valid.", "title": "Invalid bucket location"}' )
def test_wiki_content_returns_200(self): node = ProjectFactory(is_public=True) url = node.api_url_for('wiki_page_content', wname='somerandomid') res = self.app.get(url) assert_equal(res.status_code, 200)
class TestFilesViews(OsfTestCase): def setUp(self): super(TestFilesViews, self).setUp() self.user = AuthUserFactory() self.auth = ('test', self.user.api_keys[0]._primary_key) self.consolidated_auth = Auth(user=self.user) self.project = ProjectFactory(creator=self.user) self.project.add_addon('osffiles', auth=self.consolidated_auth) self.node_settings = self.project.get_addon('osffiles') self.fid = 'firstfile' self._upload_file(self.fid, 'firstcontent') def _upload_file(self, name, content, **kwargs): url = self.project.api_url + 'osffiles/' res = self.app.post( url, upload_files=[ ('file', name, content), ], auth=self.auth, **kwargs ) self.project.reload() return res def test_download_file(self): url = self.project.uploads[0].download_url(self.project) res = self.app.get(url, auth=self.user.auth).maybe_follow() assert_equal(res.body, 'firstcontent') def test_download_file_by_version_with_bad_version_value(self): url = self.project.web_url_for('download_file_by_version', fid=self.fid, vid='bad' ) res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 400) assert_in('Invalid version', res.body) def test_download_file_by_version_with_nonexistent_file(self): url = self.project.web_url_for( 'download_file_by_version', fid='notfound', vid=0 ) res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 404) def test_download_file_by_version_with_bad_version_number(self): url = self.project.web_url_for( 'download_file_by_version', fid=self.fid, vid=9999 ) res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 404) def test_download_file_by_version_with_negative_version_number(self): url = self.project.web_url_for( 'download_file_by_version', fid=self.fid, vid=-1 ) res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 400) def test_upload_file(self): node_addon = self.project.get_addon('osffiles') res = self._upload_file( 'newfile', 'a' * (node_addon.config.max_file_size) ) self.project.reload() assert_equal( self.project.logs[-1].action, 'file_added' ) assert_equal(res.status_code, 201) assert_true(isinstance(res.json, dict), 'return value is a dict') assert_equal(res.json['name'], 'newfile') assert_in('newfile', self.project.files_current) def test_upload_file_unicode_name(self): node_addon = self.project.get_addon('osffiles') res = self._upload_file( '_néwfile', 'a' * (node_addon.config.max_file_size) ) self.project.reload() assert_equal( self.project.logs[-1].action, 'file_added' ) assert_equal(res.status_code, 201) assert_true(isinstance(res.json, dict), 'return value is a dict') assert_equal(res.json['name'], '_newfile') assert_in('_newfile', self.project.files_current) def test_upload_file_too_large(self): node_addon = self.project.get_addon('osffiles') res = self._upload_file( 'newfile', 'a' * (node_addon.config.max_file_size + 1), expect_errors=True, ) self.project.reload() assert_equal(res.status_code, 400) assert_not_in('newfile', self.project.files_current) def test_file_info(self): # Upload a new version of firstfile self._upload_file(self.fid, 'secondcontent') url = self.project.api_url_for('file_info', fid=self.project.uploads[0].filename) res = self.app.get(url, auth=self.user.auth) assert_equal(res.status_code, 200) file_obj = self.project.get_file_object(self.fid, version=1) data = res.json assert_equal(data['file_name'], self.fid) assert_equal(data['registered'], self.project.is_registration) assert_equal(len(data['versions']), 2) assert_equal(data['urls']['files'], self.project.web_url_for('collect_file_trees')) assert_equal(data['urls']['latest']['download'], file_obj.download_url(self.project)) assert_equal(data['urls']['api'], file_obj.api_url(self.project)) version = res.json['versions'][0] assert_equal(version['file_name'], self.fid) assert_equal(version['version_number'], 2) assert_equal(version['modified_date'], file_obj.date_uploaded.strftime('%Y/%m/%d %I:%M %p')) assert_in('downloads', version) assert_equal(version['committer_name'], file_obj.uploader.fullname) assert_equal(version['committer_url'], file_obj.uploader.url) def test_file_info_with_anonymous_link(self): link = PrivateLinkFactory(anonymous=True) link.nodes.append(self.project) link.save() self._upload_file('firstfile', 'secondcontent') url = self.project.api_url_for( 'file_info', fid=self.project.uploads[0].filename ) res = self.app.get(url, {'view_only': link.key}) assert_not_in(self.user.fullname, res.body) assert_not_in(self.user._id, res.body) def test_delete_file(self): url = self.project.api_url_for('delete_file', fid=self.fid) res = self.app.delete(url, auth=self.auth).maybe_follow() assert_equal(res.status_code, 200) self.project.reload() assert_not_in('firstfile', self.project.files_current) def test_delete_file_returns_404_when_file_is_already_deleted(self): self.project.remove_file(Auth(self.project.creator), self.fid) url = self.project.api_url_for('delete_file', fid=self.fid) res = self.app.delete_json(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 404) def test_file_urls(self): url = self.project.api_url + 'osffiles/hgrid/' res = self.app.get(url, auth=self.auth).maybe_follow() assert_equal(len(res.json), 1) for url in ['view', 'download', 'delete']: assert_in( self.project._id, res.json[0]['urls'][url] ) def test_file_urls_fork(self): fork = self.project.fork_node(auth=Auth(user=self.user)) url = fork.api_url + 'osffiles/hgrid/' res = self.app.get(url, auth=self.auth).maybe_follow() assert_equal(len(res.json), 1) for url in ['view', 'download', 'delete']: assert_in( fork._id, res.json[0]['urls'][url] ) def test_file_urls_registration(self): registration = self.project.register_node( None, Auth(user=self.user), '', '' ) url = registration.api_url + 'osffiles/hgrid/' res = self.app.get(url, auth=self.auth).maybe_follow() assert_equal(len(res.json), 1) for url in ['view', 'download', 'delete']: assert_in( registration._id, res.json[0]['urls'][url] ) def test_view_creates_guid(self): guid_fid = 'unique' guid_content = 'snowflake' self._upload_file(guid_fid, guid_content) node_file = NodeFile.load(self.project.files_current[guid_fid]) guid_count = OsfGuidFile.find().count() # View file for the first time url = node_file.url(self.project) res = self.app.get( url, auth=self.user.auth, ).follow( auth=self.user.auth, ) guid = OsfGuidFile.find_one( Q('node', 'eq', self.project) & Q('name', 'eq', guid_fid) ) # GUID count has been incremented by one assert_equal( OsfGuidFile.find().count(), guid_count + 1 ) # Client has been redirected to GUID assert_equal( res.request.path.strip('/'), guid._id, ) # View file for the second time self.app.get( url, auth=self.user.auth, ).follow( auth=self.user.auth, ) # GUID count has not been incremented assert_equal( OsfGuidFile.find().count(), guid_count + 1 ) def test_guid_url_returns_404(self): f = NodeFile() f.save() url = '/{}/'.format(f._id) res = self.app.get(url, expect_errors=True) assert_equal(res.status_code, 404) def test_sees_delete_button_if_can_write(self): url = self.project.uploads[0].url(self.project) res = self.app.get( url, auth=self.user.auth, ).maybe_follow( auth=self.user.auth, ) assert_in('Download', res) assert_in('Delete', res) def test_does_not_see_delete_button_if_cannot_write(self): self.project.is_public = True self.project.save() user2 = AuthUserFactory() url = self.project.uploads[0].url(self.project) res = self.app.get( url, auth=user2.auth, ).maybe_follow( auth=user2.auth, ) assert_in('Download', res) assert_not_in('Delete', res)
class MendeleyViewsTestCase(OsfTestCase): def setUp(self): super(MendeleyViewsTestCase, self).setUp() self.account = MendeleyAccountFactory() self.user = AuthUserFactory(external_accounts=[self.account]) self.account.display_name = self.user.fullname self.account.save() self.user_addon = MendeleyUserSettingsFactory( owner=self.user, external_account=self.account) self.project = ProjectFactory(creator=self.user) self.node_addon = MendeleyNodeSettingsFactory(owner=self.project) self.node_addon.set_auth(external_account=self.account, user=self.user) self.provider = MendeleyCitationsProvider() #self.user_addon.grant_oauth_access(self.node_addon, self.account, metadata={'lists': 'list'}) self.node = MockNode() self.node.addon = self.node_addon self.id_patcher = mock.patch( 'website.addons.mendeley.model.Mendeley.client_id') self.secret_patcher = mock.patch( 'website.addons.mendeley.model.Mendeley.client_secret') self.id_patcher.__get__ = mock.Mock(return_value='1234567890asdf') self.secret_patcher.__get__ = mock.Mock(return_value='1234567890asdf') self.id_patcher.start() self.secret_patcher.start() def tearDown(self): self.id_patcher.stop() self.secret_patcher.stop() @mock.patch('website.addons.mendeley.model.Mendeley.client', new_callable=mock.PropertyMock) def test_check_mendeley_credentials(self, mock_client): mock_client.side_effect = HTTPError(403) assert_false(self.provider.check_credentials(self.node_addon)) mock_client.side_effect = HTTPError(402) with assert_raises(HTTPError): self.provider.check_credentials(self.node_addon) @mock.patch( 'website.addons.mendeley.views.MendeleyCitationsProvider.check_credentials' ) def test_serialize_settings_authorizer(self, mock_credentials): #"""dict: a serialized version of user-specific addon settings""" mock_credentials.return_value = True res = self.app.get( self.project.api_url_for('mendeley_get_config'), auth=self.user.auth, ) result = res.json['result'] assert_true(result['nodeHasAuth']) assert_true(result['userHasAuth']) assert_true(result['userIsOwner']) assert_true(result['validCredentials']) assert_equal(result['folder'], {'name': ''}) assert_equal(result['ownerName'], self.user.fullname) assert_true(result['urls']['auth']) assert_true(result['urls']['config']) assert_true(result['urls']['deauthorize']) assert_true(result['urls']['folders']) assert_true(result['urls']['importAuth']) assert_true(result['urls']['settings']) @mock.patch( 'website.addons.mendeley.views.MendeleyCitationsProvider.check_credentials' ) def test_serialize_settings_non_authorizer(self, mock_credentials): #"""dict: a serialized version of user-specific addon settings""" mock_credentials.return_value = True non_authorizing_user = AuthUserFactory() self.project.add_contributor(non_authorizing_user, save=True) res = self.app.get( self.project.api_url_for('mendeley_get_config'), auth=non_authorizing_user.auth, ) result = res.json['result'] assert_true(result['nodeHasAuth']) assert_false(result['userHasAuth']) assert_false(result['userIsOwner']) assert_true(result['validCredentials']) assert_equal(result['folder'], {'name': ''}) assert_equal(result['ownerName'], self.user.fullname) assert_true(result['urls']['auth']) assert_true(result['urls']['config']) assert_true(result['urls']['deauthorize']) assert_true(result['urls']['folders']) assert_true(result['urls']['importAuth']) assert_true(result['urls']['settings']) @mock.patch( 'website.addons.mendeley.provider.MendeleyCitationsProvider.check_credentials' ) def test_set_auth(self, mock_credentials): mock_credentials.return_value = True res = self.app.put_json( self.project.api_url_for('mendeley_add_user_auth'), { 'external_account_id': self.account._id, }, auth=self.user.auth, ) assert_equal(res.status_code, 200) assert_true(res.json['result']['userHasAuth']) assert_equal(self.node_addon.user_settings, self.user_addon) assert_equal(self.node_addon.external_account, self.account) def test_remove_user_auth(self): self.node_addon.set_auth(self.account, self.user) res = self.app.delete_json( self.project.api_url_for('mendeley_remove_user_auth'), { 'external_account_id': self.account._id, }, auth=self.user.auth, ) assert_equal(res.status_code, 200) self.node_addon.reload() assert_is_none(self.node_addon.user_settings) assert_is_none(self.node_addon.external_account) @mock.patch('website.addons.mendeley.model.Mendeley._folder_metadata') def test_set_config_owner(self, mock_metadata): mock_metadata.return_value = MockFolder(name='Fake Folder') # Settings config updates node settings self.node_addon.associated_user_settings = [] self.node_addon.save() res = self.app.put_json( self.project.api_url_for('mendeley_set_config'), { 'external_account_id': self.account._id, 'external_list_id': 'list', }, auth=self.user.auth, ) self.node_addon.reload() assert_equal(self.user_addon, self.node_addon.user_settings) serializer = MendeleySerializer(node_settings=self.node_addon, user_settings=self.user_addon) expected = {'result': serializer.serialized_node_settings} assert_equal(res.json, expected) @mock.patch('website.addons.mendeley.model.Mendeley._folder_metadata') def test_set_config_not_owner(self, mock_metadata): mock_metadata.return_value = MockFolder(name='Fake Folder') user = AuthUserFactory() user.add_addon('mendeley') self.project.add_contributor(user) self.project.save() res = self.app.put_json( self.project.api_url_for('mendeley_set_config'), { 'external_account_id': self.account._id, 'external_list_id': 'list', }, auth=user.auth, ) self.node_addon.reload() assert_equal(self.user_addon, self.node_addon.user_settings) serializer = MendeleySerializer(node_settings=self.node_addon, user_settings=None) expected = {'result': serializer.serialized_node_settings} assert_equal(res.json, expected) def test_mendeley_widget_view_complete(self): # JSON: everything a widget needs assert_false(self.node_addon.complete) assert_equal(self.node_addon.mendeley_list_id, None) self.node_addon.set_target_folder('ROOT-ID', 'ROOT', auth=Auth(user=self.user)) url = self.project.api_url_for('mendeley_widget') res = self.app.get(url, auth=self.user.auth).json assert_true(res['complete']) assert_equal(res['list_id'], 'ROOT-ID') def test_widget_view_incomplete(self): # JSON: tell the widget when it hasn't been configured assert_false(self.node_addon.complete) assert_equal(self.node_addon.mendeley_list_id, None) url = self.project.api_url_for('mendeley_widget') res = self.app.get(url, auth=self.user.auth).json assert_false(res['complete']) assert_is_none(res['list_id']) @httpretty.activate def test_mendeley_citation_list_root(self): httpretty.register_uri(httpretty.GET, urlparse.urljoin(API_URL, 'folders'), body=mock_responses['folders'], content_type='application/json') res = self.app.get(self.project.api_url_for('mendeley_citation_list'), auth=self.user.auth) root = res.json['contents'][0] assert_equal(root['kind'], 'folder') assert_equal(root['id'], 'ROOT') assert_equal(root['parent_list_id'], '__') @httpretty.activate def test_mendeley_citation_list_non_root(self): httpretty.register_uri(httpretty.GET, urlparse.urljoin(API_URL, 'folders'), body=mock_responses['folders'], content_type='application/json') httpretty.register_uri(httpretty.GET, urlparse.urljoin(API_URL, 'documents'), body=mock_responses['documents'], content_type='application/json') res = self.app.get(self.project.api_url_for('mendeley_citation_list', mendeley_list_id='ROOT'), auth=self.user.auth) children = res.json['contents'] assert_equal(len(children), 7) assert_equal(children[0]['kind'], 'folder') assert_equal(children[1]['kind'], 'file') assert_true(children[1].get('csl') is not None) @httpretty.activate def test_mendeley_citation_list_non_linked_or_child_non_authorizer(self): non_authorizing_user = AuthUserFactory() self.project.add_contributor(non_authorizing_user, save=True) self.node_addon.mendeley_list_id = 'e843da05-8818-47c2-8c37-41eebfc4fe3f' self.node_addon.save() httpretty.register_uri(httpretty.GET, urlparse.urljoin(API_URL, 'folders'), body=mock_responses['folders'], content_type='application/json') httpretty.register_uri(httpretty.GET, urlparse.urljoin(API_URL, 'documents'), body=mock_responses['documents'], content_type='application/json') res = self.app.get(self.project.api_url_for('mendeley_citation_list', mendeley_list_id='ROOT'), auth=non_authorizing_user.auth, expect_errors=True) assert_equal(res.status_code, 403)
class TestFilesViews(OsfTestCase): def setUp(self): super(TestFilesViews, self).setUp() self.user = AuthUserFactory() self.auth = ('test', self.user.api_keys[0]._primary_key) self.consolidated_auth = Auth(user=self.user) self.project = ProjectFactory(creator=self.user) self.project.add_addon('osffiles', auth=self.consolidated_auth) self.node_settings = self.project.get_addon('osffiles') self.fid = 'firstfile' self._upload_file(self.fid, 'firstcontent') def _upload_file(self, name, content, **kwargs): url = self.project.api_url + 'osffiles/' res = self.app.post(url, upload_files=[ ('file', name, content), ], auth=self.auth, **kwargs) self.project.reload() return res def test_download_file(self): url = self.project.uploads[0].download_url(self.project) res = self.app.get(url, auth=self.user.auth).maybe_follow() assert_equal(res.body, 'firstcontent') def test_download_file_by_version_with_bad_version_value(self): url = self.project.web_url_for('download_file_by_version', fid=self.fid, vid='bad') res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 400) assert_in('Invalid version', res.body) def test_download_file_by_version_with_nonexistent_file(self): url = self.project.web_url_for('download_file_by_version', fid='notfound', vid=0) res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 404) def test_download_file_by_version_with_bad_version_number(self): url = self.project.web_url_for('download_file_by_version', fid=self.fid, vid=9999) res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 404) def test_download_file_by_version_with_negative_version_number(self): url = self.project.web_url_for('download_file_by_version', fid=self.fid, vid=-1) res = self.app.get(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 400) def test_upload_file(self): node_addon = self.project.get_addon('osffiles') res = self._upload_file('newfile', 'a' * (node_addon.config.max_file_size)) self.project.reload() assert_equal(self.project.logs[-1].action, 'file_added') assert_equal(res.status_code, 201) assert_true(isinstance(res.json, dict), 'return value is a dict') assert_equal(res.json['name'], 'newfile') assert_in('newfile', self.project.files_current) def test_upload_file_unicode_name(self): node_addon = self.project.get_addon('osffiles') res = self._upload_file('_néwfile', 'a' * (node_addon.config.max_file_size)) self.project.reload() assert_equal(self.project.logs[-1].action, 'file_added') assert_equal(res.status_code, 201) assert_true(isinstance(res.json, dict), 'return value is a dict') assert_equal(res.json['name'], '_newfile') assert_in('_newfile', self.project.files_current) def test_upload_file_too_large(self): node_addon = self.project.get_addon('osffiles') res = self._upload_file( 'newfile', 'a' * (node_addon.config.max_file_size + 1), expect_errors=True, ) self.project.reload() assert_equal(res.status_code, 400) assert_not_in('newfile', self.project.files_current) def test_file_info(self): # Upload a new version of firstfile self._upload_file(self.fid, 'secondcontent') url = self.project.api_url_for('file_info', fid=self.project.uploads[0].filename) res = self.app.get(url, auth=self.user.auth) assert_equal(res.status_code, 200) file_obj = self.project.get_file_object(self.fid, version=1) data = res.json assert_equal(data['file_name'], self.fid) assert_equal(data['registered'], self.project.is_registration) assert_equal(len(data['versions']), 2) assert_equal(data['urls']['files'], self.project.web_url_for('collect_file_trees')) assert_equal(data['urls']['latest']['download'], file_obj.download_url(self.project)) assert_equal(data['urls']['api'], file_obj.api_url(self.project)) version = res.json['versions'][0] assert_equal(version['file_name'], self.fid) assert_equal(version['version_number'], 2) assert_equal(version['modified_date'], file_obj.date_uploaded.strftime('%Y/%m/%d %I:%M %p')) assert_in('downloads', version) assert_equal(version['committer_name'], file_obj.uploader.fullname) assert_equal(version['committer_url'], file_obj.uploader.url) def test_file_info_with_anonymous_link(self): link = PrivateLinkFactory(anonymous=True) link.nodes.append(self.project) link.save() self._upload_file('firstfile', 'secondcontent') url = self.project.api_url_for('file_info', fid=self.project.uploads[0].filename) res = self.app.get(url, {'view_only': link.key}) assert_not_in(self.user.fullname, res.body) assert_not_in(self.user._id, res.body) def test_delete_file(self): url = self.project.api_url_for('delete_file', fid=self.fid) res = self.app.delete(url, auth=self.auth).maybe_follow() assert_equal(res.status_code, 200) self.project.reload() assert_not_in('firstfile', self.project.files_current) def test_delete_file_returns_404_when_file_is_already_deleted(self): self.project.remove_file(Auth(self.project.creator), self.fid) url = self.project.api_url_for('delete_file', fid=self.fid) res = self.app.delete_json(url, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 404) def test_file_urls(self): url = self.project.api_url + 'osffiles/hgrid/' res = self.app.get(url, auth=self.auth).maybe_follow() assert_equal(len(res.json), 1) for url in ['view', 'download', 'delete']: assert_in(self.project._id, res.json[0]['urls'][url]) def test_file_urls_fork(self): fork = self.project.fork_node(auth=Auth(user=self.user)) url = fork.api_url + 'osffiles/hgrid/' res = self.app.get(url, auth=self.auth).maybe_follow() assert_equal(len(res.json), 1) for url in ['view', 'download', 'delete']: assert_in(fork._id, res.json[0]['urls'][url]) def test_file_urls_registration(self): registration = self.project.register_node(None, Auth(user=self.user), '', '') url = registration.api_url + 'osffiles/hgrid/' res = self.app.get(url, auth=self.auth).maybe_follow() assert_equal(len(res.json), 1) for url in ['view', 'download', 'delete']: assert_in(registration._id, res.json[0]['urls'][url]) def test_view_creates_guid(self): guid_fid = 'unique' guid_content = 'snowflake' self._upload_file(guid_fid, guid_content) node_file = NodeFile.load(self.project.files_current[guid_fid]) guid_count = OsfGuidFile.find().count() # View file for the first time url = node_file.url(self.project) res = self.app.get( url, auth=self.user.auth, ).follow(auth=self.user.auth, ) guid = OsfGuidFile.find_one( Q('node', 'eq', self.project) & Q('name', 'eq', guid_fid)) # GUID count has been incremented by one assert_equal(OsfGuidFile.find().count(), guid_count + 1) # Client has been redirected to GUID assert_equal( res.request.path.strip('/'), guid._id, ) # View file for the second time self.app.get( url, auth=self.user.auth, ).follow(auth=self.user.auth, ) # GUID count has not been incremented assert_equal(OsfGuidFile.find().count(), guid_count + 1) def test_guid_url_returns_404(self): f = NodeFile() f.save() url = '/{}/'.format(f._id) res = self.app.get(url, expect_errors=True) assert_equal(res.status_code, 404) def test_sees_delete_button_if_can_write(self): url = self.project.uploads[0].url(self.project) res = self.app.get( url, auth=self.user.auth, ).maybe_follow(auth=self.user.auth, ) assert_in('Download', res) assert_in('Delete', res) def test_does_not_see_delete_button_if_cannot_write(self): self.project.is_public = True self.project.save() user2 = AuthUserFactory() url = self.project.uploads[0].url(self.project) res = self.app.get( url, auth=user2.auth, ).maybe_follow(auth=user2.auth, ) assert_in('Download', res) assert_not_in('Delete', res)
class RegistrationEmbargoViewsTestCase(OsfTestCase): def setUp(self): super(RegistrationEmbargoViewsTestCase, self).setUp() ensure_schemas() self.user = AuthUserFactory() self.project = ProjectFactory(creator=self.user) self.registration = RegistrationFactory(project=self.project, creator=self.user) current_month = datetime.datetime.now().strftime("%B") current_year = datetime.datetime.now().strftime("%Y") self.valid_make_public_payload = json.dumps( { u"embargoEndDate": u"Fri, 01, {month} {year} 00:00:00 GMT".format( month=current_month, year=current_year ), u"registrationChoice": "immediate", u"summary": unicode(fake.sentence()), } ) valid_date = datetime.datetime.now() + datetime.timedelta(days=180) self.valid_embargo_payload = json.dumps( { u"embargoEndDate": unicode(valid_date.strftime("%a, %d, %B %Y %H:%M:%S")) + u" GMT", u"registrationChoice": "embargo", u"summary": unicode(fake.sentence()), } ) self.invalid_embargo_date_payload = json.dumps( { u"embargoEndDate": u"Thu, 01 {month} {year} 05:00:00 GMT".format( month=current_month, year=str(int(current_year) - 1) ), u"registrationChoice": "embargo", u"summary": unicode(fake.sentence()), } ) @mock.patch("framework.tasks.handlers.enqueue_task") def test_POST_register_make_public_immediately_creates_registration_approval(self, mock_enqueue): res = self.app.post( self.project.api_url_for("node_register_template_page_post", template=u"Open-Ended_Registration"), self.valid_make_public_payload, content_type="application/json", auth=self.user.auth, ) assert_equal(res.status_code, 201) registration = Node.find().sort("-registered_date")[0] assert_true(registration.is_registration) assert_not_equal(registration.registration_approval, None) # Regression test for https://openscience.atlassian.net/browse/OSF-5039 @mock.patch("framework.tasks.handlers.enqueue_task") def test_POST_register_make_public_immediately_creates_private_pending_registration_for_public_project( self, mock_enqueue ): public_project = ProjectFactory(is_public=True, creator=self.user) component = NodeFactory(creator=self.user, parent=public_project, title="Component", is_public=True) subproject = ProjectFactory(creator=self.user, parent=public_project, title="Subproject", is_public=True) subproject_component = NodeFactory(creator=self.user, parent=subproject, title="Subcomponent", is_public=True) res = self.app.post( public_project.api_url_for("node_register_template_page_post", template=u"Open-Ended_Registration"), self.valid_make_public_payload, content_type="application/json", auth=self.user.auth, ) public_project.reload() assert_equal(res.status_code, 201) # Last node directly registered from self.project registration = Node.load(public_project.node__registrations[-1]) assert_true(registration.is_registration) assert_false(registration.is_public) for node in registration.get_descendants_recursive(): assert_true(node.is_registration) assert_false(node.is_public) @mock.patch("framework.tasks.handlers.enqueue_task") def test_POST_register_make_public_does_not_make_children_public(self, mock_enqueue): component = NodeFactory(creator=self.user, parent=self.project, title="Component") subproject = ProjectFactory(creator=self.user, parent=self.project, title="Subproject") subproject_component = NodeFactory(creator=self.user, parent=subproject, title="Subcomponent") res = self.app.post( self.project.api_url_for("node_register_template_page_post", template=u"Open-Ended_Registration"), self.valid_make_public_payload, content_type="application/json", auth=self.user.auth, ) self.project.reload() # Last node directly registered from self.project registration = Node.load(self.project.node__registrations[-1]) assert_false(registration.is_public) for node in registration.get_descendants_recursive(): assert_true(node.is_registration) assert_false(node.is_public) @mock.patch("framework.tasks.handlers.enqueue_task") def test_POST_register_embargo_is_not_public(self, mock_enqueue): res = self.app.post( self.project.api_url_for("node_register_template_page_post", template=u"Open-Ended_Registration"), self.valid_embargo_payload, content_type="application/json", auth=self.user.auth, ) assert_equal(res.status_code, 201) registration = Node.find().sort("-registered_date")[0] assert_true(registration.is_registration) assert_false(registration.is_public) assert_true(registration.is_pending_embargo_for_existing_registration) assert_is_not_none(registration.embargo) # Regression test for https://openscience.atlassian.net/browse/OSF-5071 @mock.patch("framework.tasks.handlers.enqueue_task") def test_POST_register_embargo_does_not_make_project_or_children_public(self, mock_enqueue): public_project = ProjectFactory(creator=self.user, is_public=True) component = NodeFactory(creator=self.user, parent=public_project, title="Component", is_public=True) subproject = ProjectFactory(creator=self.user, parent=public_project, title="Subproject", is_public=True) subproject_component = NodeFactory(creator=self.user, parent=subproject, title="Subcomponent", is_public=True) res = self.app.post( public_project.api_url_for("node_register_template_page_post", template=u"Open-Ended_Registration"), self.valid_embargo_payload, content_type="application/json", auth=self.user.auth, ) public_project.reload() assert_equal(res.status_code, 201) # Last node directly registered from self.project registration = Node.load(public_project.node__registrations[-1]) assert_true(registration.is_registration) assert_false(registration.is_public) assert_true(registration.is_pending_embargo_for_existing_registration) assert_is_not_none(registration.embargo) for node in registration.get_descendants_recursive(): assert_true(node.is_registration) assert_false(node.is_public) @mock.patch("framework.tasks.handlers.enqueue_task") def test_POST_invalid_embargo_end_date_returns_HTTPBad_Request(self, mock_enqueue): res = self.app.post( self.project.api_url_for("node_register_template_page_post", template=u"Open-Ended_Registration"), self.invalid_embargo_date_payload, content_type="application/json", auth=self.user.auth, expect_errors=True, ) assert_equal(res.status_code, 400) @mock.patch("framework.tasks.handlers.enqueue_task") def test_valid_POST_embargo_adds_to_parent_projects_log(self, mock_enquque): initial_project_logs = len(self.project.logs) res = self.app.post( self.project.api_url_for("node_register_template_page_post", template=u"Open-Ended_Registration"), self.valid_embargo_payload, content_type="application/json", auth=self.user.auth, ) self.project.reload() # Logs: Created, registered, embargo initiated assert_equal(len(self.project.logs), initial_project_logs + 1) def test_non_contributor_GET_approval_returns_HTTPError(self): non_contributor = AuthUserFactory() self.registration.embargo_registration(self.user, datetime.datetime.utcnow() + datetime.timedelta(days=10)) self.registration.save() assert_true(self.registration.is_pending_embargo) approval_token = self.registration.embargo.approval_state[self.user._id]["approval_token"] approval_url = self.registration.web_url_for("view_project", token=approval_token) res = self.app.get(approval_url, auth=non_contributor.auth, expect_errors=True) assert_equal(http.FORBIDDEN, res.status_code) assert_true(self.registration.is_pending_embargo) assert_false(self.registration.embargo_end_date) def test_non_contributor_GET_disapproval_returns_HTTPError(self): non_contributor = AuthUserFactory() self.registration.embargo_registration(self.user, datetime.datetime.utcnow() + datetime.timedelta(days=10)) self.registration.save() assert_true(self.registration.is_pending_embargo) rejection_token = self.registration.embargo.approval_state[self.user._id]["rejection_token"] approval_url = self.registration.web_url_for("view_project", token=rejection_token) res = self.app.get(approval_url, auth=non_contributor.auth, expect_errors=True) assert_equal(http.FORBIDDEN, res.status_code) assert_true(self.registration.is_pending_embargo) assert_false(self.registration.embargo_end_date)
class TestRmapNodeViews(OsfTestCase): def setUp(self): super(TestRmapNodeViews, self).setUp() self.user = AuthUserFactory() self.project = ProjectFactory(creator=self.user, is_public=True) self.url = self.project.api_url_for('node_rmap_post') self._old_rmap_url = settings.RMAP_BASE_URL self._old_rmap_pass = settings.RMAP_PASS settings.RMAP_BASE_URL = 'rmaptest.test/' settings.RMAP_PASS = '******' self._set_up_mock_response_for_node(self.project) def _set_up_mock_response_for_node(self, node): rmap_url = _rmap_url_for_node(node) httpretty.register_uri(httpretty.POST, rmap_url, body='abc123', status=200) def tearDown(self): super(TestRmapNodeViews, self).tearDown() settings.RMAP_BASE_URL = self._old_rmap_url settings.RMAP_PASS = self._old_rmap_pass def test_rmap_get_valid_no_disco_id(self): res = self.app.get(self.url, auth=self.user.auth) assert_equal(res.status_code, 200) assert_equal(res.json['disco_id'], None) def test_rmap_get_valid_with_disco_id(self): disco_id = 'pan1cath3d1sc0' self.project.set_identifier_value('disco', disco_id) res = self.app.get(self.url, auth=self.user.auth) assert_equal(res.status_code, 200) assert_equal(res.json['disco_id'], disco_id) def test_rmap_post_valid(self): res = self.app.post_json(self.url, {}, auth=self.user.auth) assert_equal(res.status_code, 201) self.project.reload() rmap_id = self.project.get_identifier('disco') assert_true(bool(rmap_id)) assert_equal(rmap_id.value, 'abc123') def test_rmap_post_non_contributor_should_error(self): noncontrib = AuthUserFactory() res = self.app.post_json(self.url, {}, auth=noncontrib.auth, expect_errors=True) assert_equal(res.status_code, 403) def test_rmap_post_non_admin_contributor_should_error(self): non_admin = AuthUserFactory() self.project.add_contributor(non_admin, permissions=['read', 'write'], auth=Auth(self.user)) self.project.save() res = self.app.post_json(self.url, {}, auth=non_admin.auth, expect_errors=True) assert_equal(res.status_code, 403) def test_rmap_post_non_public_project_should_error(self): private_project = ProjectFactory(creator=self.user, is_public=False) url = private_project.api_url_for('node_rmap_post') res = self.app.post_json(url, {}, auth=self.user.auth, expect_errors=True) assert_equal(res.status_code, 400)