Example #1
0
class TestDropboxNodeSettingsModel(OsfTestCase):

    def setUp(self):
        super(TestDropboxNodeSettingsModel, self).setUp()
        self.user = UserFactory()
        self.user.add_addon('dropbox')
        self.user.save()
        self.user_settings = self.user.get_addon('dropbox')
        self.project = ProjectFactory()
        self.node_settings = DropboxNodeSettingsFactory(
            user_settings=self.user_settings,
            owner=self.project
        )

    def test_fields(self):
        node_settings = DropboxNodeSettings(user_settings=self.user_settings)
        node_settings.save()
        assert_true(node_settings.user_settings)
        assert_equal(node_settings.user_settings.owner, self.user)
        assert_true(hasattr(node_settings, 'folder'))
        assert_true(hasattr(node_settings, 'registration_data'))

    def test_folder_defaults_to_none(self):
        node_settings = DropboxNodeSettings(user_settings=self.user_settings)
        node_settings.save()
        assert_is_none(node_settings.folder)

    def test_has_auth(self):
        settings = DropboxNodeSettings(user_settings=self.user_settings)
        settings.save()
        assert_false(settings.has_auth)

        settings.user_settings.access_token = '123abc'
        settings.user_settings.save()
        assert_true(settings.has_auth)

    def test_to_json(self):
        settings = self.node_settings
        user = UserFactory()
        result = settings.to_json(user)
        assert_equal(result['addon_short_name'], 'dropbox')

    def test_delete(self):
        assert_true(self.node_settings.user_settings)
        assert_true(self.node_settings.folder)
        old_logs = self.project.logs
        self.node_settings.delete()
        self.node_settings.save()
        assert_is(self.node_settings.user_settings, None)
        assert_is(self.node_settings.folder, None)
        assert_true(self.node_settings.deleted)
        assert_equal(self.project.logs, old_logs)

    def test_deauthorize(self):
        assert_true(self.node_settings.user_settings)
        assert_true(self.node_settings.folder)
        self.node_settings.deauthorize(auth=Auth(self.user))
        self.node_settings.save()
        assert_is(self.node_settings.user_settings, None)
        assert_is(self.node_settings.folder, None)

        last_log = self.project.logs[-1]
        assert_equal(last_log.action, 'dropbox_node_deauthorized')
        params = last_log.params
        assert_in('node', params)
        assert_in('project', params)
        assert_in('folder', params)

    def test_set_folder(self):
        folder_name = 'queen/freddie'
        self.node_settings.set_folder(folder_name, auth=Auth(self.user))
        self.node_settings.save()
        # Folder was set
        assert_equal(self.node_settings.folder, folder_name)
        # Log was saved
        last_log = self.project.logs[-1]
        assert_equal(last_log.action, 'dropbox_folder_selected')

    def test_set_user_auth(self):
        node_settings = DropboxNodeSettingsFactory()
        user_settings = DropboxUserSettingsFactory()

        node_settings.set_user_auth(user_settings)
        node_settings.save()

        assert_true(node_settings.has_auth)
        assert_equal(node_settings.user_settings, user_settings)
        # A log was saved
        last_log = node_settings.owner.logs[-1]
        assert_equal(last_log.action, 'dropbox_node_authorized')
        log_params = last_log.params
        assert_equal(log_params['folder'], node_settings.folder)
        assert_equal(log_params['node'], node_settings.owner._primary_key)
        assert_equal(last_log.user, user_settings.owner)

    def test_serialize_credentials(self):
        self.user_settings.access_token = 'secret'
        self.user_settings.save()
        credentials = self.node_settings.serialize_waterbutler_credentials()
        expected = {'token': self.node_settings.user_settings.access_token}
        assert_equal(credentials, expected)

    def test_serialize_credentials_not_authorized(self):
        self.node_settings.user_settings = None
        self.node_settings.save()
        with assert_raises(exceptions.AddonError):
            self.node_settings.serialize_waterbutler_credentials()

    def test_serialize_settings(self):
        settings = self.node_settings.serialize_waterbutler_settings()
        expected = {'folder': self.node_settings.folder}
        assert_equal(settings, expected)

    def test_serialize_settings_not_configured(self):
        self.node_settings.folder = None
        self.node_settings.save()
        with assert_raises(exceptions.AddonError):
            self.node_settings.serialize_waterbutler_settings()

    def test_create_log(self):
        action = 'file_added'
        path = 'pizza.nii'
        nlog = len(self.project.logs)
        self.node_settings.create_waterbutler_log(
            auth=Auth(user=self.user),
            action=action,
            metadata={'path': path},
        )
        self.project.reload()
        assert_equal(len(self.project.logs), nlog + 1)
        assert_equal(
            self.project.logs[-1].action,
            'dropbox_{0}'.format(action),
        )
        assert_equal(
            self.project.logs[-1].params['path'],
            os.path.join(self.node_settings.folder, path),
        )

    def test_does_not_get_copied_to_registrations(self):
        registration = self.project.register_node(
            schema=None,
            auth=Auth(user=self.project.creator),
            template='Template1',
            data='hodor'
        )
        assert_false(registration.has_addon('dropbox'))
Example #2
0
class TestDropboxNodeSettingsModel(OsfTestCase):
    def setUp(self):
        super(TestDropboxNodeSettingsModel, self).setUp()
        self.user = UserFactory()
        self.user.add_addon('dropbox')
        self.user.save()
        self.user_settings = self.user.get_addon('dropbox')
        self.project = ProjectFactory()
        self.node_settings = DropboxNodeSettingsFactory(
            user_settings=self.user_settings, owner=self.project)

    def test_complete_true(self):
        self.node_settings.user_settings.access_token = 'seems legit'

        assert_true(self.node_settings.has_auth)
        assert_true(self.node_settings.complete)

    def test_complete_false(self):
        self.node_settings.user_settings.access_token = 'seems legit'
        self.node_settings.folder = None

        assert_true(self.node_settings.has_auth)
        assert_false(self.node_settings.complete)

    def test_complete_auth_false(self):
        self.node_settings.user_settings = None

        assert_false(self.node_settings.has_auth)
        assert_false(self.node_settings.complete)

    def test_fields(self):
        node_settings = DropboxNodeSettings(user_settings=self.user_settings)
        node_settings.save()
        assert_true(node_settings.user_settings)
        assert_equal(node_settings.user_settings.owner, self.user)
        assert_true(hasattr(node_settings, 'folder'))
        assert_true(hasattr(node_settings, 'registration_data'))

    def test_folder_defaults_to_none(self):
        node_settings = DropboxNodeSettings(user_settings=self.user_settings)
        node_settings.save()
        assert_is_none(node_settings.folder)

    def test_has_auth(self):
        settings = DropboxNodeSettings(user_settings=self.user_settings)
        settings.save()
        assert_false(settings.has_auth)

        settings.user_settings.access_token = '123abc'
        settings.user_settings.save()
        assert_true(settings.has_auth)

    def test_to_json(self):
        settings = self.node_settings
        user = UserFactory()
        result = settings.to_json(user)
        assert_equal(result['addon_short_name'], 'dropbox')

    def test_delete(self):
        assert_true(self.node_settings.user_settings)
        assert_true(self.node_settings.folder)
        old_logs = self.project.logs
        self.node_settings.delete()
        self.node_settings.save()
        assert_is(self.node_settings.user_settings, None)
        assert_is(self.node_settings.folder, None)
        assert_true(self.node_settings.deleted)
        assert_equal(self.project.logs, old_logs)

    def test_deauthorize(self):
        assert_true(self.node_settings.user_settings)
        assert_true(self.node_settings.folder)
        self.node_settings.deauthorize(auth=Auth(self.user))
        self.node_settings.save()
        assert_is(self.node_settings.user_settings, None)
        assert_is(self.node_settings.folder, None)

        last_log = self.project.logs[-1]
        assert_equal(last_log.action, 'dropbox_node_deauthorized')
        params = last_log.params
        assert_in('node', params)
        assert_in('project', params)
        assert_in('folder', params)

    def test_set_folder(self):
        folder_name = 'queen/freddie'
        self.node_settings.set_folder(folder_name, auth=Auth(self.user))
        self.node_settings.save()
        # Folder was set
        assert_equal(self.node_settings.folder, folder_name)
        # Log was saved
        last_log = self.project.logs[-1]
        assert_equal(last_log.action, 'dropbox_folder_selected')

    def test_set_user_auth(self):
        node_settings = DropboxNodeSettingsFactory()
        user_settings = DropboxUserSettingsFactory()

        node_settings.set_user_auth(user_settings)
        node_settings.save()

        assert_true(node_settings.has_auth)
        assert_equal(node_settings.user_settings, user_settings)
        # A log was saved
        last_log = node_settings.owner.logs[-1]
        assert_equal(last_log.action, 'dropbox_node_authorized')
        log_params = last_log.params
        assert_equal(log_params['folder'], node_settings.folder)
        assert_equal(log_params['node'], node_settings.owner._primary_key)
        assert_equal(last_log.user, user_settings.owner)

    def test_serialize_credentials(self):
        self.user_settings.access_token = 'secret'
        self.user_settings.save()
        credentials = self.node_settings.serialize_waterbutler_credentials()
        expected = {'token': self.node_settings.user_settings.access_token}
        assert_equal(credentials, expected)

    def test_serialize_credentials_not_authorized(self):
        self.node_settings.user_settings = None
        self.node_settings.save()
        with assert_raises(exceptions.AddonError):
            self.node_settings.serialize_waterbutler_credentials()

    def test_serialize_settings(self):
        settings = self.node_settings.serialize_waterbutler_settings()
        expected = {'folder': self.node_settings.folder}
        assert_equal(settings, expected)

    def test_serialize_settings_not_configured(self):
        self.node_settings.folder = None
        self.node_settings.save()
        with assert_raises(exceptions.AddonError):
            self.node_settings.serialize_waterbutler_settings()

    def test_create_log(self):
        action = 'file_added'
        path = 'pizza.nii'
        self.node_settings.folder = '/SomeOddPath'
        self.node_settings.save()
        nlog = len(self.project.logs)
        self.node_settings.create_waterbutler_log(
            auth=Auth(user=self.user),
            action=action,
            metadata={'path': path},
        )
        self.project.reload()
        assert_equal(len(self.project.logs), nlog + 1)
        assert_equal(
            self.project.logs[-1].action,
            'dropbox_{0}'.format(action),
        )
        assert_equal(
            self.project.logs[-1].params['path'],
            path,
        )

    @mock.patch('website.archiver.tasks.archive')
    def test_does_not_get_copied_to_registrations(self, mock_archive):
        registration = self.project.register_node(
            schema=None,
            auth=Auth(user=self.project.creator),
            template='Template1',
            data='hodor')
        assert_false(registration.has_addon('dropbox'))
Example #3
0
class TestS3ViewsConfig(OsfTestCase):

    def setUp(self):

        super(TestS3ViewsConfig, 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()
        self.node_url = '/api/v1/project/{0}/'.format(self.project._id)

    @mock.patch('website.addons.s3.views.config.does_bucket_exist')
    @mock.patch('website.addons.s3.views.config.adjust_cors')
    def test_s3_settings_no_bucket(self, mock_cors, mock_does_bucket_exist):
        mock_does_bucket_exist.return_value = False
        mock_cors.return_value = True
        url = self.project.api_url + 's3/settings/'
        rv = self.app.post_json(url, {}, expect_errors=True, auth=self.user.auth)
        assert_true('trouble' in rv.body)

    @mock.patch('website.addons.s3.views.config.does_bucket_exist')
    @mock.patch('website.addons.s3.views.config.adjust_cors')
    def test_s3_set_bucket(self, mock_cors, mock_exist):

        mock_cors.return_value = True
        mock_exist.return_value = True

        url = self.project.api_url + 's3/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 + 's3/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 + 's3/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 + 's3/settings/'
        res = self.app.post_json(
            url, {'s3_bucket': 'hammertofall'}, auth=user.auth,
            expect_errors=True
        )
        assert_equal(res.status_code, http.BAD_REQUEST)

    @mock.patch('website.addons.s3.api.S3Wrapper.from_addon')
    def test_s3_set_bucket_registered(self, mock_from_addon):

        mock_from_addon.return_value = create_mock_wrapper()

        registration = self.project.register_node(
            None, self.consolidated_auth, '', ''
        )

        url = registration.api_url + 's3/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.has_access')
    @mock.patch('website.addons.s3.views.config.create_osf_user')
    def test_user_settings(self, mock_user, mock_access):
        mock_access.return_value = True
        mock_user.return_value = (
            'osf-user-12345',
            {
                'access_key_id': 'scout',
                'secret_access_key': 'ssshhhhhhhhh'
            }
        )
        url = '/api/v1/settings/s3/'
        self.app.post_json(
            url,
            {
                'access_key': 'scout',
                'secret_key': 'Atticus'
            },
            auth=self.user.auth
        )
        self.user_settings.reload()
        assert_equals(self.user_settings.access_key, 'scout')

    @mock.patch('website.addons.s3.model.AddonS3UserSettings.remove_iam_user')
    def test_s3_remove_user_settings(self, mock_access):
        mock_access.return_value = True
        self.user_settings.access_key = 'to-kill-a-mocking-bucket'
        self.user_settings.secret_key = 'itsasecret'
        self.user_settings.save()
        url = '/api/v1/settings/s3/'
        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)
        assert_equals(mock_access.call_count, 1)

    @mock.patch('website.addons.s3.model.AddonS3UserSettings.remove_iam_user')
    def test_s3_remove_user_settings_none(self, mock_access):
        self.user_settings.access_key = None
        self.user_settings.secret_key = None
        self.user_settings.save()
        url = '/api/v1/settings/s3/'
        self.app.delete(url, auth=self.user.auth)
        self.user_settings.reload()
        assert_equals(mock_access.call_count, 0)

    @mock.patch('website.addons.s3.views.config.has_access')
    def test_user_settings_no_auth(self, mock_access):
        mock_access.return_value = False
        url = '/api/v1/settings/s3/'
        rv = self.app.post_json(url, {}, auth=self.user.auth, expect_errors=True)
        assert_equals(rv.status_int, http.BAD_REQUEST)

    @mock.patch('website.addons.s3.views.config.has_access')
    @mock.patch('website.addons.s3.views.config.create_osf_user')
    def test_node_settings_no_user_settings(self, mock_user, mock_access):
        self.node_settings.user_settings = None
        self.node_settings.save()
        url = self.node_url + 's3/authorize/'

        mock_access.return_value = True
        mock_user.return_value = (
            'osf-user-12345',
            {
                'access_key_id': 'scout',
                'secret_access_key': 'ssshhhhhhhhh'
            }
        )
        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')

    def test_node_settings_no_user_settings_ui(self):
        self.node_settings.user_settings.access_key = None
        self.node_settings.user_settings = None
        self.node_settings.save()
        url = self.project.url + 'settings/'
        rv = self.app.get(url, auth=self.user.auth)
        assert_true('<label for="s3Addon">Access Key</label>' in rv.body)

    @mock.patch('website.addons.s3.model.get_bucket_drop_down')
    def test_node_settings_user_settings_ui(self, mock_dropdown):
        mock_dropdown.return_value = ['mybucket']
        url = self.project.url + 'settings/'
        rv = self.app.get(url, auth=self.user.auth)
        assert_true('mybucket' in rv.body)
Example #4
0
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)
Example #5
0
class TestCallbacks(OsfTestCase):

    def setUp(self):

        super(TestCallbacks, self).setUp()

        self.user = AuthUserFactory()
        self.consolidated_auth = Auth(user=self.user)
        self.auth = self.user.auth
        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 = 'singlefile'
        self.node_settings.save()

    def test_update_fields_project(self):
        num_logs = len(self.project.logs)
        # try updating fields
        newfields = {
            'type': 'project',
            'id': '313131',
            'name': 'A PROJECT'
        }
        self.node_settings.update_fields(newfields, self.project, Auth(self.project.creator))
        #check for updated
        assert_equals(self.node_settings.figshare_id, '313131')
        assert_equals(self.node_settings.figshare_type, 'project')
        assert_equals(self.node_settings.figshare_title, 'A PROJECT')
        # check for log added
        assert_equals(len(self.project.logs), num_logs + 1)

    def test_update_fields_fileset(self):
        num_logs = len(self.project.logs)
        # try updating fields
        newfields = {
            'type': 'fileset',
            'id': '313131',
            'name': 'A FILESET'
        }
        self.node_settings.update_fields(newfields, self.project, Auth(self.project.creator))
        #check for updated
        assert_equals(self.node_settings.figshare_id, '313131')
        assert_equals(self.node_settings.figshare_type, 'fileset')
        assert_equals(self.node_settings.figshare_title, 'A FILESET')
        # check for log added
        assert_equals(len(self.project.logs), num_logs + 1)

    def test_update_fields_some_missing(self):
        num_logs = len(self.project.logs)
        # try updating fields
        newfields = {
            'type': 'project',
            'id': '313131',
            'name': 'A PROJECT'
        }
        self.node_settings.update_fields(newfields, self.project, Auth(self.project.creator))
        #check for updated
        assert_equals(self.node_settings.figshare_id, '313131')
        assert_equals(self.node_settings.figshare_title, 'A PROJECT')
        # check for log added
        assert_equals(len(self.project.logs), num_logs + 1)

    def test_update_fields_invalid(self):
        num_logs = len(self.project.logs)
        # try updating fields
        newfields = {
            'adad': 131313,
            'i1513': '313131',
            'titladad': 'A PROJECT'
        }
        self.node_settings.update_fields(newfields, self.project, Auth(self.project.creator))
        #check for updated
        assert_equals(self.node_settings.figshare_id, '123456')
        assert_equals(self.node_settings.figshare_type, 'project')
        assert_equals(self.node_settings.figshare_title, 'singlefile')
        # check for log added
        assert_equals(len(self.project.logs), num_logs)

    def test_api_url_no_user(self):
        self.node_settings.user_settings = None
        self.node_settings.save()
        assert_equal(self.node_settings.api_url, figshare_settings.API_URL)

    def test_api_url(self):
        assert_equal(self.node_settings.api_url, figshare_settings.API_OAUTH_URL)

    def test_before_register_linked_content(self):
        assert_false(
            self.node_settings.before_register(
                self.project,
                self.project.creator
            ) is None
        )

    def test_before_register_no_linked_content(self):
        self.node_settings.figshare_id = None
        assert_true(
            self.node_settings.before_register(
                self.project,
                self.project.creator
            ) is None
        )

    def test_before_remove_contributor_authenticator(self):
        message = self.node_settings.before_remove_contributor(
            self.project, self.project.creator
        )
        assert_true(message)

    def test_before_remove_contributor_not_authenticator(self):
        message = self.node_settings.before_remove_contributor(
            self.project, self.non_authenticator
        )
        assert_false(message)

    def test_after_remove_contributor_authenticator_not_self(self):
        auth = Auth(user=self.non_authenticator)
        msg = self.node_settings.after_remove_contributor(
            self.project, self.project.creator, auth
        )

        assert_in(
            self.project.project_or_component,
            msg
        )
        assert_equal(
            self.node_settings.user_settings,
            None
        )
        assert_in("You can re-authenticate", msg)

    def test_after_remove_contributor_authenticator_self(self):
        msg = self.node_settings.after_remove_contributor(
            self.project, self.project.creator, self.consolidated_auth
        )

        assert_in(
            self.project.title,
            msg
        )
        assert_equal(
            self.node_settings.user_settings,
            None
        )
        assert_not_in("You can re-authenticate", msg)

    def test_after_fork_authenticator(self):
        fork = ProjectFactory()
        clone, message = self.node_settings.after_fork(
            self.project, fork, self.project.creator,
        )
        assert_equal(
            self.node_settings.user_settings,
            clone.user_settings,
        )

    def test_after_fork_not_authenticator(self):
        fork = ProjectFactory()
        clone, message = self.node_settings.after_fork(
            self.project, fork, self.non_authenticator,
        )
        assert_equal(
            clone.user_settings,
            None,
        )

    def test_after_delete(self):
        self.project.remove_node(Auth(user=self.project.creator))
        # Ensure that changes to node settings have been saved
        self.node_settings.reload()
        assert_true(self.node_settings.user_settings is None)
        assert_true(self.node_settings.figshare_id is None)
        assert_true(self.node_settings.figshare_type is None)
        assert_true(self.node_settings.figshare_title is None)

    @mock.patch('website.archiver.tasks.archive')
    @mock.patch('website.addons.figshare.model.AddonFigShareNodeSettings.archive_errors')
    def test_does_not_get_copied_to_registrations(self, mock_errors, mock_archive):
        registration = self.project.register_node(
            schema=None,
            auth=Auth(user=self.project.creator),
            template='Template1',
            data='hodor'
        )
        assert_false(registration.has_addon('figshare'))
Example #6
0
class TestS3ViewsConfig(OsfTestCase):
    def setUp(self):

        super(TestS3ViewsConfig, 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()
        self.node_url = '/api/v1/project/{0}/'.format(self.project._id)

    @mock.patch('website.addons.s3.views.config.does_bucket_exist')
    @mock.patch('website.addons.s3.views.config.adjust_cors')
    def test_s3_settings_no_bucket(self, mock_cors, mock_does_bucket_exist):
        mock_does_bucket_exist.return_value = False
        mock_cors.return_value = True
        url = self.project.api_url + 's3/settings/'
        rv = self.app.post_json(url, {},
                                expect_errors=True,
                                auth=self.user.auth)
        assert_true('trouble' in rv.body)

    @mock.patch('website.addons.s3.views.config.does_bucket_exist')
    @mock.patch('website.addons.s3.views.config.adjust_cors')
    @mock.patch('website.addons.s3.utils.get_bucket_drop_down')
    def test_s3_set_bucket(self, mock_cors, mock_exist, mock_dropdown):

        mock_cors.return_value = True
        mock_exist.return_value = True
        mock_dropdown.return_value = ['mybucket']
        url = self.project.api_url_for('s3_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 + 's3/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 + 's3/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 + 's3/settings/'
        res = self.app.post_json(url, {'s3_bucket': 'hammertofall'},
                                 auth=user.auth,
                                 expect_errors=True)
        assert_equal(res.status_code, http.BAD_REQUEST)

    @mock.patch('website.addons.s3.api.S3Wrapper.from_addon')
    def test_s3_set_bucket_registered(self, mock_from_addon):

        mock_from_addon.return_value = create_mock_wrapper()

        registration = self.project.register_node(None, self.consolidated_auth,
                                                  '', '')

        url = registration.api_url + 's3/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.has_access')
    @mock.patch('website.addons.s3.views.config.create_osf_user')
    def test_user_settings(self, mock_user, mock_access):
        mock_access.return_value = True
        mock_user.return_value = ('osf-user-12345', {
            'access_key_id': 'scout',
            'secret_access_key': 'ssshhhhhhhhh'
        })
        url = '/api/v1/settings/s3/'
        self.app.post_json(url, {
            'access_key': 'scout',
            'secret_key': 'Atticus'
        },
                           auth=self.user.auth)
        self.user_settings.reload()
        assert_equals(self.user_settings.access_key, 'scout')

    @mock.patch('website.addons.s3.model.AddonS3UserSettings.remove_iam_user')
    def test_s3_remove_user_settings(self, mock_access):
        mock_access.return_value = True
        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_remove_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)
        assert_equals(mock_access.call_count, 1)

    @mock.patch('website.addons.s3.model.AddonS3UserSettings.remove_iam_user')
    def test_s3_remove_user_settings_none(self, mock_access):
        self.user_settings.access_key = None
        self.user_settings.secret_key = None
        self.user_settings.save()
        url = api_url_for('s3_remove_user_settings')
        self.app.delete(url, auth=self.user.auth)
        self.user_settings.reload()
        assert_equals(mock_access.call_count, 0)

    @mock.patch('website.addons.s3.views.config.has_access')
    def test_user_settings_no_auth(self, mock_access):
        mock_access.return_value = False
        url = '/api/v1/settings/s3/'
        rv = self.app.post_json(url, {},
                                auth=self.user.auth,
                                expect_errors=True)
        assert_equals(rv.status_int, http.BAD_REQUEST)

    @mock.patch('website.addons.s3.utils.get_bucket_drop_down')
    @mock.patch('website.addons.s3.views.config.has_access')
    @mock.patch('website.addons.s3.views.config.create_osf_user')
    def test_node_settings_no_user_settings(self, mock_user, mock_access,
                                            mock_dropdown):
        self.node_settings.user_settings = None
        self.node_settings.save()
        url = self.node_url + 's3/authorize/'

        mock_access.return_value = True
        mock_user.return_value = ('osf-user-12345', {
            'access_key_id': 'scout',
            'secret_access_key': 'ssshhhhhhhhh'
        })
        mock_dropdown.return_value = ['mybucket']
        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.utils.get_bucket_drop_down')
    def test_node_settings_no_user_settings_ui(self, mock_dropdown):
        mock_dropdown.return_value = ['mybucket']
        self.node_settings.user_settings.access_key = None
        self.node_settings.user_settings = None
        self.node_settings.save()
        url = self.project.url + 'settings/'
        rv = self.app.get(url, auth=self.user.auth)
        assert_true('<label for="s3Addon">Access Key</label>' in rv.body)

    @mock.patch('website.addons.s3.utils.get_bucket_list')
    def test_s3_bucket_list(self, mock_bucket_list):
        fake_buckets = [
            MockS3Bucket(name=fake.domain_word()) for i in range(10)
        ]
        mock_bucket_list.return_value = fake_buckets
        url = self.node_settings.owner.api_url_for('s3_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_remove_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_remove_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)

        expected_bucket = self.node_settings.bucket
        expected_node_has_auth = True
        expected_user_is_owner = True
        result = res.json['result']
        assert_equal(result['bucket'], expected_bucket)
        assert_equal(result['node_has_auth'], expected_node_has_auth)
        assert_equal(result['user_is_owner'], expected_user_is_owner)

    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)

        expected_bucket = self.node_settings.bucket
        expected_node_has_auth = True
        expected_user_is_owner = False
        result = res.json['result']
        assert_equal(result['bucket'], expected_bucket)
        assert_equal(result['node_has_auth'], expected_node_has_auth)
        assert_equal(result['user_is_owner'], expected_user_is_owner)

    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.add_s3_auth')
    def test_s3_authorize_node_valid(self, mock_add):
        mock_add.return_value = True
        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_invalid(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.add_s3_auth')
    def test_s3_authorize_node_malformed(self, mock_add):
        mock_add.return_value = False
        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_equal(res.json['message'], 'Incorrect credentials')
        assert_equal(res.status_code, 400)

    @mock.patch('website.addons.s3.views.config.add_s3_auth')
    def test_s3_authorize_node_unauthorized(self, mock_add):
        mock_add.return_value = True
        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.add_s3_auth')
    def test_s3_authorize_user_valid(self, mock_add):
        mock_add.return_value = True
        url = self.project.api_url_for('s3_authorize_user')
        cred = {
            'access_key': fake.password(),
            'secret_key': fake.password(),
        }
        res = self.app.post_json(url, cred, auth=self.user.auth)
        assert_equal(res.json, {})

    def test_s3_authorize_user_invalid(self):
        url = self.project.api_url_for('s3_authorize_user')
        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.add_s3_auth')
    def test_s3_authorize_user_malformed(self, mock_add):
        mock_add.return_value = False
        url = self.project.api_url_for('s3_authorize_user')
        cred = {
            'access_key': fake.password(),
            'secret_key': fake.password(),
        }
        res = self.app.post_json(url,
                                 cred,
                                 auth=self.user.auth,
                                 expect_errors=True)
        assert_equal(res.json['message'], 'Incorrect credentials')
        assert_equal(res.status_code, 400)

    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)
Example #7
0
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(get_default_metaschema(),
                                                  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)
Example #8
0
class TestAddonFileViews(OsfTestCase):

    @classmethod
    def setUpClass(cls):
        super(TestAddonFileViews, cls).setUpClass()
        PROVIDER_MAP['github'] = [TestFolder, TestFile, TestFileNode]
        TestFileNode.provider = 'github'

    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 = GitHubAccountFactory()
        self.oauth.save()

        self.user.external_accounts.append(self.oauth)
        self.user.save()

        self.node_addon.user_settings = self.user_addon
        self.node_addon.external_account = self.oauth
        self.node_addon.repo = 'Truth'
        self.node_addon.user = '******'
        self.node_addon.save()

    @classmethod
    def tearDownClass(cls):
        super(TestAddonFileViews, cls).tearDownClass()
        PROVIDER_MAP['github'] = [models.GithubFolder, models.GithubFile, models.GithubFileNode]
        del PROVIDER_MAP['test_addons']
        TrashedFileNode.remove()

    def get_test_file(self):
        version = models.FileVersion(identifier='1')
        version.save()
        versions = [version]
        ret = TestFile(
            name='Test',
            node=self.project,
            path='/test/Test',
            materialized_path='/test/Test',
            versions=versions
        )
        ret.save()
        return ret

    def get_second_test_file(self):
        version = models.FileVersion(identifier='1')
        version.save()
        ret = TestFile(
            name='Test2',
            node=self.project,
            path='/test/Test2',
            materialized_path='/test/Test2',
            versions=[version]
        )
        ret.save()
        return ret

    def get_mako_return(self):
        ret = serialize_node(self.project, Auth(self.user), primary=True)
        ret.update({
            'error': '',
            'provider': '',
            'file_path': '',
            'sharejs_uuid': '',
            'private': '',
            'urls': {
                'files': '',
                'render': '',
                'sharejs': '',
                'mfr': '',
                'gravatar': '',
                'external': '',
                'archived_from': '',
            },
            'size': '',
            'extra': '',
            'file_name': '',
            'materialized_path': '',
            'file_id': '',
        })
        ret.update(rubeus.collect_addon_assets(self.project))
        return ret

    def test_redirects_to_guid(self):
        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        resp = self.app.get(
            self.project.web_url_for(
                'addon_view_or_download_file',
                path=file_node.path.strip('/'),
                provider='github'
            ),
            auth=self.user.auth
        )

        assert_equals(resp.status_code, 302)
        assert_equals(resp.location, 'http://*****:*****@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()

        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        mock_view_file.return_value = self.get_mako_return()

        self.app.get('/{}/?action=view'.format(guid._id), auth=self.user.auth)

        args, kwargs = mock_view_file.call_args
        assert_equals(kwargs, {})
        assert_equals(args[0].user._id, self.user._id)
        assert_equals(args[1], self.project)
        assert_equals(args[2], file_node)
        assert_true(isinstance(args[3], file_node.touch(None).__class__))

    @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()

        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        mock_view_file.return_value = self.get_mako_return()

        self.app.get('/{}/'.format(guid._id), auth=self.user.auth)

        args, kwargs = mock_view_file.call_args
        assert_equals(kwargs, {})
        assert_equals(args[0].user._id, self.user._id)
        assert_equals(args[1], self.project)
        assert_equals(args[2], file_node)
        assert_true(isinstance(args[3], file_node.touch(None).__class__))

    def test_download_create_guid(self):
        file_node = self.get_test_file()
        assert_is(file_node.get_guid(), None)

        self.app.get(
            self.project.web_url_for(
                'addon_view_or_download_file',
                path=file_node.path.strip('/'),
                provider='github',
            ),
            auth=self.user.auth
        )

        assert_true(file_node.get_guid())

    def test_view_file_does_not_delete_file_when_requesting_invalid_version(self):
        with mock.patch('website.addons.github.model.GitHubNodeSettings.is_private',
                        new_callable=mock.PropertyMock) as mock_is_private:
            mock_is_private.return_value = False

            file_node = self.get_test_file()
            assert_is(file_node.get_guid(), None)

            url = self.project.web_url_for(
                'addon_view_or_download_file',
                path=file_node.path.strip('/'),
                provider='github',
            )
            # First view generated GUID
            self.app.get(url, auth=self.user.auth)

            self.app.get(url + '?version=invalid', auth=self.user.auth, expect_errors=True)

            assert_is_not_none(StoredFileNode.load(file_node._id))
            assert_is_none(TrashedFileNode.load(file_node._id))

    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, 401)

    def test_nonstorage_addons_raise(self):
        resp = self.app.get(
            self.project.web_url_for(
                'addon_view_or_download_file',
                path='sillywiki',
                provider='wiki',
                action='download'
            ),
            auth=self.user.auth,
            expect_errors=True
        )

        assert_equals(resp.status_code, 400)

    def test_head_returns_url(self):
        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        resp = self.app.head('/{}/'.format(guid._id), auth=self.user.auth)
        location = furl.furl(resp.location)
        assert_urls_equal(location.url, file_node.generate_waterbutler_url(direct=None, version=None))

    def test_head_returns_url_with_version(self):
        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        resp = self.app.head('/{}/?revision=1&foo=bar'.format(guid._id), auth=self.user.auth)
        location = furl.furl(resp.location)
        # Note: version is added but us but all other url params are added as well
        assert_urls_equal(location.url, file_node.generate_waterbutler_url(direct=None, revision=1, version=None, foo='bar'))

    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.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, 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.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, 401)

    def test_delete_action_creates_trashed_file_node(self):
        file_node = self.get_test_file()
        payload = {
            'provider': file_node.provider,
            'metadata': {
                'path': '/test/Test',
                'materialized': '/test/Test'
            }
        }
        views.addon_delete_file_node(self=None, node=self.project, user=self.user, event_type='file_removed', payload=payload)
        assert_false(StoredFileNode.load(file_node._id))
        assert_true(TrashedFileNode.load(file_node._id))

    def test_delete_action_for_folder_deletes_subfolders_and_creates_trashed_file_nodes(self):
        file_node = self.get_test_file()
        subfolder = TestFolder(
            name='folder',
            node=self.project,
            path='/test/folder/',
            materialized_path='/test/folder/',
            versions=[]
        )
        subfolder.save()
        payload = {
            'provider': file_node.provider,
            'metadata': {
                'path': '/test/',
                'materialized': '/test/'
            }
        }
        views.addon_delete_file_node(self=None, node=self.project, user=self.user, event_type='file_removed', payload=payload)
        assert_false(StoredFileNode.load(file_node._id))
        assert_true(TrashedFileNode.load(file_node._id))
        assert_false(StoredFileNode.load(subfolder._id))

    @mock.patch('website.archiver.tasks.archive')
    def test_archived_from_url(self, mock_archive):
        file_node = self.get_test_file()
        second_file_node = self.get_second_test_file()
        file_node.copied_from = second_file_node

        registered_node = self.project.register_node(
            schema=get_default_metaschema(),
            auth=Auth(self.user),
            data=None,
        )

        archived_from_url = views.get_archived_from_url(registered_node, file_node)
        view_url = self.project.web_url_for('addon_view_or_download_file', provider=file_node.provider, path=file_node.copied_from._id)
        assert_true(archived_from_url)
        assert_urls_equal(archived_from_url, view_url)

    @mock.patch('website.archiver.tasks.archive')
    def test_archived_from_url_without_copied_from(self, mock_archive):
        file_node = self.get_test_file()

        registered_node = self.project.register_node(
            schema=get_default_metaschema(),
            auth=Auth(self.user),
            data=None,
        )
        archived_from_url = views.get_archived_from_url(registered_node, file_node)
        assert_false(archived_from_url)

    @mock.patch('website.archiver.tasks.archive')
    def test_copied_from_id_trashed(self, mock_archive):
        file_node = self.get_test_file()
        second_file_node = self.get_second_test_file()
        file_node.copied_from = second_file_node
        self.project.register_node(
            schema=get_default_metaschema(),
            auth=Auth(self.user),
            data=None,
        )
        trashed_node = second_file_node.delete()
        assert_false(trashed_node.copied_from)
Example #9
0
class TestS3ViewsConfig(OsfTestCase):

    def setUp(self):

        super(TestS3ViewsConfig, 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()
        self.node_url = '/api/v1/project/{0}/'.format(self.project._id)

    @mock.patch('website.addons.s3.views.config.does_bucket_exist')
    @mock.patch('website.addons.s3.views.config.adjust_cors')
    def test_s3_settings_no_bucket(self, mock_cors, mock_does_bucket_exist):
        mock_does_bucket_exist.return_value = False
        mock_cors.return_value = True
        url = self.project.api_url + 's3/settings/'
        rv = self.app.post_json(url, {}, expect_errors=True, auth=self.user.auth)
        assert_true('trouble' in rv.body)

    @mock.patch('website.addons.s3.views.config.does_bucket_exist')
    @mock.patch('website.addons.s3.views.config.adjust_cors')
    @mock.patch('website.addons.s3.utils.get_bucket_drop_down')
    def test_s3_set_bucket(self, mock_cors, mock_exist, mock_dropdown):

        mock_cors.return_value = True
        mock_exist.return_value = True
        mock_dropdown.return_value = ['mybucket']
        url = self.project.api_url_for('s3_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 + 's3/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 + 's3/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 + 's3/settings/'
        res = self.app.post_json(
            url, {'s3_bucket': 'hammertofall'}, auth=user.auth,
            expect_errors=True
        )
        assert_equal(res.status_code, http.BAD_REQUEST)

    @mock.patch('website.addons.s3.api.S3Wrapper.from_addon')
    def test_s3_set_bucket_registered(self, mock_from_addon):

        mock_from_addon.return_value = create_mock_wrapper()

        registration = self.project.register_node(
            None, self.consolidated_auth, '', ''
        )

        url = registration.api_url + 's3/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.has_access')
    @mock.patch('website.addons.s3.views.config.create_osf_user')
    def test_user_settings(self, mock_user, mock_access):
        mock_access.return_value = True
        mock_user.return_value = (
            'osf-user-12345',
            {
                'access_key_id': 'scout',
                'secret_access_key': 'ssshhhhhhhhh'
            }
        )
        url = '/api/v1/settings/s3/'
        self.app.post_json(
            url,
            {
                'access_key': 'scout',
                'secret_key': 'Atticus'
            },
            auth=self.user.auth
        )
        self.user_settings.reload()
        assert_equals(self.user_settings.access_key, 'scout')

    @mock.patch('website.addons.s3.model.AddonS3UserSettings.remove_iam_user')
    def test_s3_remove_user_settings(self, mock_access):
        mock_access.return_value = True
        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_remove_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)
        assert_equals(mock_access.call_count, 1)

    @mock.patch('website.addons.s3.model.AddonS3UserSettings.remove_iam_user')
    def test_s3_remove_user_settings_none(self, mock_access):
        self.user_settings.access_key = None
        self.user_settings.secret_key = None
        self.user_settings.save()
        url = api_url_for('s3_remove_user_settings')
        self.app.delete(url, auth=self.user.auth)
        self.user_settings.reload()
        assert_equals(mock_access.call_count, 0)

    @mock.patch('website.addons.s3.views.config.has_access')
    def test_user_settings_no_auth(self, mock_access):
        mock_access.return_value = False
        url = '/api/v1/settings/s3/'
        rv = self.app.post_json(url, {}, auth=self.user.auth, expect_errors=True)
        assert_equals(rv.status_int, http.BAD_REQUEST)

    @mock.patch('website.addons.s3.utils.get_bucket_drop_down')
    @mock.patch('website.addons.s3.views.config.has_access')
    @mock.patch('website.addons.s3.views.config.create_osf_user')
    def test_node_settings_no_user_settings(self, mock_user, mock_access, mock_dropdown):
        self.node_settings.user_settings = None
        self.node_settings.save()
        url = self.node_url + 's3/authorize/'

        mock_access.return_value = True
        mock_user.return_value = (
            'osf-user-12345',
            {
                'access_key_id': 'scout',
                'secret_access_key': 'ssshhhhhhhhh'
            }
        )
        mock_dropdown.return_value = ['mybucket']
        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.utils.get_bucket_drop_down')
    def test_node_settings_no_user_settings_ui(self, mock_dropdown):
        mock_dropdown.return_value = ['mybucket']
        self.node_settings.user_settings.access_key = None
        self.node_settings.user_settings = None
        self.node_settings.save()
        url = self.project.url + 'settings/'
        rv = self.app.get(url, auth=self.user.auth)
        assert_true('<label for="s3Addon">Access Key</label>' in rv.body)

    @mock.patch('website.addons.s3.utils.get_bucket_list')
    def test_s3_bucket_list(self, mock_bucket_list):
        fake_buckets = [
            MockS3Bucket(name=fake.domain_word())
            for i in range(10)
        ]
        mock_bucket_list.return_value = fake_buckets
        url = self.node_settings.owner.api_url_for('s3_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_remove_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_remove_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)

        expected_bucket = self.node_settings.bucket
        expected_node_has_auth = True
        expected_user_is_owner = True
        result = res.json['result']
        assert_equal(result['bucket'], expected_bucket)
        assert_equal(result['node_has_auth'], expected_node_has_auth)
        assert_equal(result['user_is_owner'], expected_user_is_owner)

    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)

        expected_bucket = self.node_settings.bucket
        expected_node_has_auth = True
        expected_user_is_owner = False
        result = res.json['result']
        assert_equal(result['bucket'], expected_bucket)
        assert_equal(result['node_has_auth'], expected_node_has_auth)
        assert_equal(result['user_is_owner'], expected_user_is_owner)

    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.add_s3_auth')
    def test_s3_authorize_node_valid(self, mock_add):
        mock_add.return_value = True
        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_invalid(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.add_s3_auth')
    def test_s3_authorize_node_malformed(self, mock_add):
        mock_add.return_value = False
        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_equal(res.json['message'], 'Incorrect credentials')
        assert_equal(res.status_code, 400)

    @mock.patch('website.addons.s3.views.config.add_s3_auth')
    def test_s3_authorize_node_unauthorized(self, mock_add):
        mock_add.return_value = True
        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.add_s3_auth')
    def test_s3_authorize_user_valid(self, mock_add):
        mock_add.return_value = True
        url = self.project.api_url_for('s3_authorize_user')
        cred = {
            'access_key': fake.password(),
            'secret_key': fake.password(),
        }
        res = self.app.post_json(url, cred, auth=self.user.auth)
        assert_equal(res.json, {})

    def test_s3_authorize_user_invalid(self):
        url = self.project.api_url_for('s3_authorize_user')
        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.add_s3_auth')
    def test_s3_authorize_user_malformed(self, mock_add):
        mock_add.return_value = False
        url = self.project.api_url_for('s3_authorize_user')
        cred = {
            'access_key': fake.password(),
            'secret_key': fake.password(),
        }
        res = self.app.post_json(url, cred, auth=self.user.auth, expect_errors=True)
        assert_equal(res.json['message'], 'Incorrect credentials')
        assert_equal(res.status_code, 400)

    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)
Example #10
0
class TestDropboxNodeSettingsModel(OsfTestCase):
    def setUp(self):
        super(TestDropboxNodeSettingsModel, self).setUp()
        self.user = UserFactory()
        self.user.add_addon("dropbox")
        self.user.save()
        self.user_settings = self.user.get_addon("dropbox")
        self.project = ProjectFactory()
        self.node_settings = DropboxNodeSettingsFactory(user_settings=self.user_settings, owner=self.project)

    def test_complete_true(self):
        self.node_settings.user_settings.access_token = "seems legit"

        assert_true(self.node_settings.has_auth)
        assert_true(self.node_settings.complete)

    def test_complete_false(self):
        self.node_settings.user_settings.access_token = "seems legit"
        self.node_settings.folder = None

        assert_true(self.node_settings.has_auth)
        assert_false(self.node_settings.complete)

    def test_complete_auth_false(self):
        self.node_settings.user_settings = None

        assert_false(self.node_settings.has_auth)
        assert_false(self.node_settings.complete)

    def test_fields(self):
        node_settings = DropboxNodeSettings(user_settings=self.user_settings)
        node_settings.save()
        assert_true(node_settings.user_settings)
        assert_equal(node_settings.user_settings.owner, self.user)
        assert_true(hasattr(node_settings, "folder"))
        assert_true(hasattr(node_settings, "registration_data"))

    def test_folder_defaults_to_none(self):
        node_settings = DropboxNodeSettings(user_settings=self.user_settings)
        node_settings.save()
        assert_is_none(node_settings.folder)

    def test_has_auth(self):
        settings = DropboxNodeSettings(user_settings=self.user_settings)
        settings.save()
        assert_false(settings.has_auth)

        settings.user_settings.access_token = "123abc"
        settings.user_settings.save()
        assert_true(settings.has_auth)

    def test_to_json(self):
        settings = self.node_settings
        user = UserFactory()
        result = settings.to_json(user)
        assert_equal(result["addon_short_name"], "dropbox")

    def test_delete(self):
        assert_true(self.node_settings.user_settings)
        assert_true(self.node_settings.folder)
        old_logs = self.project.logs
        self.node_settings.delete()
        self.node_settings.save()
        assert_is(self.node_settings.user_settings, None)
        assert_is(self.node_settings.folder, None)
        assert_true(self.node_settings.deleted)
        assert_equal(self.project.logs, old_logs)

    def test_deauthorize(self):
        assert_true(self.node_settings.user_settings)
        assert_true(self.node_settings.folder)
        self.node_settings.deauthorize(auth=Auth(self.user))
        self.node_settings.save()
        assert_is(self.node_settings.user_settings, None)
        assert_is(self.node_settings.folder, None)

        last_log = self.project.logs[-1]
        assert_equal(last_log.action, "dropbox_node_deauthorized")
        params = last_log.params
        assert_in("node", params)
        assert_in("project", params)
        assert_in("folder", params)

    def test_set_folder(self):
        folder_name = "queen/freddie"
        self.node_settings.set_folder(folder_name, auth=Auth(self.user))
        self.node_settings.save()
        # Folder was set
        assert_equal(self.node_settings.folder, folder_name)
        # Log was saved
        last_log = self.project.logs[-1]
        assert_equal(last_log.action, "dropbox_folder_selected")

    def test_set_user_auth(self):
        node_settings = DropboxNodeSettingsFactory()
        user_settings = DropboxUserSettingsFactory()

        node_settings.set_user_auth(user_settings)
        node_settings.save()

        assert_true(node_settings.has_auth)
        assert_equal(node_settings.user_settings, user_settings)
        # A log was saved
        last_log = node_settings.owner.logs[-1]
        assert_equal(last_log.action, "dropbox_node_authorized")
        log_params = last_log.params
        assert_equal(log_params["folder"], node_settings.folder)
        assert_equal(log_params["node"], node_settings.owner._primary_key)
        assert_equal(last_log.user, user_settings.owner)

    def test_serialize_credentials(self):
        self.user_settings.access_token = "secret"
        self.user_settings.save()
        credentials = self.node_settings.serialize_waterbutler_credentials()
        expected = {"token": self.node_settings.user_settings.access_token}
        assert_equal(credentials, expected)

    def test_serialize_credentials_not_authorized(self):
        self.node_settings.user_settings = None
        self.node_settings.save()
        with assert_raises(exceptions.AddonError):
            self.node_settings.serialize_waterbutler_credentials()

    def test_serialize_settings(self):
        settings = self.node_settings.serialize_waterbutler_settings()
        expected = {"folder": self.node_settings.folder}
        assert_equal(settings, expected)

    def test_serialize_settings_not_configured(self):
        self.node_settings.folder = None
        self.node_settings.save()
        with assert_raises(exceptions.AddonError):
            self.node_settings.serialize_waterbutler_settings()

    def test_create_log(self):
        action = "file_added"
        path = "pizza.nii"
        self.node_settings.folder = "/SomeOddPath"
        self.node_settings.save()
        nlog = len(self.project.logs)
        self.node_settings.create_waterbutler_log(auth=Auth(user=self.user), action=action, metadata={"path": path})
        self.project.reload()
        assert_equal(len(self.project.logs), nlog + 1)
        assert_equal(self.project.logs[-1].action, "dropbox_{0}".format(action))
        assert_equal(self.project.logs[-1].params["path"], path)

    @mock.patch("website.archiver.tasks.archive")
    def test_does_not_get_copied_to_registrations(self, mock_archive):
        registration = self.project.register_node(
            schema=None, auth=Auth(user=self.project.creator), template="Template1", data="hodor"
        )
        assert_false(registration.has_addon("dropbox"))
Example #11
0
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(get_default_metaschema(), 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)
Example #12
0
class TestAddonFileViews(OsfTestCase):
    @classmethod
    def setUpClass(cls):
        super(TestAddonFileViews, cls).setUpClass()
        PROVIDER_MAP['github'] = [TestFolder, TestFile, TestFileNode]
        TestFileNode.provider = 'github'

    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 = GitHubAccountFactory()
        self.oauth.save()

        self.user.external_accounts.append(self.oauth)
        self.user.save()

        self.node_addon.user_settings = self.user_addon
        self.node_addon.external_account = self.oauth
        self.node_addon.repo = 'Truth'
        self.node_addon.user = '******'
        self.node_addon.save()

    @classmethod
    def tearDownClass(cls):
        super(TestAddonFileViews, cls).tearDownClass()
        PROVIDER_MAP['github'] = [
            models.GithubFolder, models.GithubFile, models.GithubFileNode
        ]
        del PROVIDER_MAP['test_addons']
        TrashedFileNode.remove()

    def get_test_file(self):
        version = models.FileVersion(identifier='1')
        version.save()
        versions = [version]
        ret = TestFile(name='Test',
                       node=self.project,
                       path='/test/Test',
                       materialized_path='/test/Test',
                       versions=versions)
        ret.save()
        return ret

    def get_second_test_file(self):
        version = models.FileVersion(identifier='1')
        version.save()
        ret = TestFile(name='Test2',
                       node=self.project,
                       path='/test/Test2',
                       materialized_path='/test/Test2',
                       versions=[version])
        ret.save()
        return ret

    def get_mako_return(self):
        ret = serialize_node(self.project, Auth(self.user), primary=True)
        ret.update({
            'error': '',
            'provider': '',
            'file_path': '',
            'sharejs_uuid': '',
            'private': '',
            'urls': {
                'files': '',
                'render': '',
                'sharejs': '',
                'mfr': '',
                'gravatar': '',
                'external': '',
                'archived_from': '',
            },
            'size': '',
            'extra': '',
            'file_name': '',
            'materialized_path': '',
            'file_id': '',
        })
        ret.update(rubeus.collect_addon_assets(self.project))
        return ret

    def test_redirects_to_guid(self):
        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        resp = self.app.get(self.project.web_url_for(
            'addon_view_or_download_file',
            path=file_node.path.strip('/'),
            provider='github'),
                            auth=self.user.auth)

        assert_equals(resp.status_code, 302)
        assert_equals(resp.location,
                      'http://*****:*****@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()

        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        mock_view_file.return_value = self.get_mako_return()

        self.app.get('/{}/?action=view'.format(guid._id), auth=self.user.auth)

        args, kwargs = mock_view_file.call_args
        assert_equals(kwargs, {})
        assert_equals(args[0].user._id, self.user._id)
        assert_equals(args[1], self.project)
        assert_equals(args[2], file_node)
        assert_true(isinstance(args[3], file_node.touch(None).__class__))

    @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()

        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        mock_view_file.return_value = self.get_mako_return()

        self.app.get('/{}/'.format(guid._id), auth=self.user.auth)

        args, kwargs = mock_view_file.call_args
        assert_equals(kwargs, {})
        assert_equals(args[0].user._id, self.user._id)
        assert_equals(args[1], self.project)
        assert_equals(args[2], file_node)
        assert_true(isinstance(args[3], file_node.touch(None).__class__))

    def test_download_create_guid(self):
        file_node = self.get_test_file()
        assert_is(file_node.get_guid(), None)

        self.app.get(self.project.web_url_for(
            'addon_view_or_download_file',
            path=file_node.path.strip('/'),
            provider='github',
        ),
                     auth=self.user.auth)

        assert_true(file_node.get_guid())

    def test_view_file_does_not_delete_file_when_requesting_invalid_version(
            self):
        with mock.patch(
                'website.addons.github.model.GitHubNodeSettings.is_private',
                new_callable=mock.PropertyMock) as mock_is_private:
            mock_is_private.return_value = False

            file_node = self.get_test_file()
            assert_is(file_node.get_guid(), None)

            url = self.project.web_url_for(
                'addon_view_or_download_file',
                path=file_node.path.strip('/'),
                provider='github',
            )
            # First view generated GUID
            self.app.get(url, auth=self.user.auth)

            self.app.get(url + '?version=invalid',
                         auth=self.user.auth,
                         expect_errors=True)

            assert_is_not_none(StoredFileNode.load(file_node._id))
            assert_is_none(TrashedFileNode.load(file_node._id))

    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, 401)

    def test_nonstorage_addons_raise(self):
        resp = self.app.get(self.project.web_url_for(
            'addon_view_or_download_file',
            path='sillywiki',
            provider='wiki',
            action='download'),
                            auth=self.user.auth,
                            expect_errors=True)

        assert_equals(resp.status_code, 400)

    def test_head_returns_url(self):
        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        resp = self.app.head('/{}/'.format(guid._id), auth=self.user.auth)
        location = furl.furl(resp.location)
        assert_urls_equal(
            location.url,
            file_node.generate_waterbutler_url(direct=None, version=None))

    def test_head_returns_url_with_version(self):
        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        resp = self.app.head('/{}/?revision=1&foo=bar'.format(guid._id),
                             auth=self.user.auth)
        location = furl.furl(resp.location)
        # Note: version is added but us but all other url params are added as well
        assert_urls_equal(
            location.url,
            file_node.generate_waterbutler_url(direct=None,
                                               revision=1,
                                               version=None,
                                               foo='bar'))

    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.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, 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.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, 401)

    def test_delete_action_creates_trashed_file_node(self):
        file_node = self.get_test_file()
        payload = {
            'provider': file_node.provider,
            'metadata': {
                'path': '/test/Test',
                'materialized': '/test/Test'
            }
        }
        views.addon_delete_file_node(self=None,
                                     node=self.project,
                                     user=self.user,
                                     event_type='file_removed',
                                     payload=payload)
        assert_false(StoredFileNode.load(file_node._id))
        assert_true(TrashedFileNode.load(file_node._id))

    def test_delete_action_for_folder_deletes_subfolders_and_creates_trashed_file_nodes(
            self):
        file_node = self.get_test_file()
        subfolder = TestFolder(name='folder',
                               node=self.project,
                               path='/test/folder/',
                               materialized_path='/test/folder/',
                               versions=[])
        subfolder.save()
        payload = {
            'provider': file_node.provider,
            'metadata': {
                'path': '/test/',
                'materialized': '/test/'
            }
        }
        views.addon_delete_file_node(self=None,
                                     node=self.project,
                                     user=self.user,
                                     event_type='file_removed',
                                     payload=payload)
        assert_false(StoredFileNode.load(file_node._id))
        assert_true(TrashedFileNode.load(file_node._id))
        assert_false(StoredFileNode.load(subfolder._id))

    @mock.patch('website.archiver.tasks.archive')
    def test_archived_from_url(self, mock_archive):
        file_node = self.get_test_file()
        second_file_node = self.get_second_test_file()
        file_node.copied_from = second_file_node

        registered_node = self.project.register_node(
            schema=get_default_metaschema(),
            auth=Auth(self.user),
            data=None,
        )

        archived_from_url = views.get_archived_from_url(
            registered_node, file_node)
        view_url = self.project.web_url_for('addon_view_or_download_file',
                                            provider=file_node.provider,
                                            path=file_node.copied_from._id)
        assert_true(archived_from_url)
        assert_urls_equal(archived_from_url, view_url)

    @mock.patch('website.archiver.tasks.archive')
    def test_archived_from_url_without_copied_from(self, mock_archive):
        file_node = self.get_test_file()

        registered_node = self.project.register_node(
            schema=get_default_metaschema(),
            auth=Auth(self.user),
            data=None,
        )
        archived_from_url = views.get_archived_from_url(
            registered_node, file_node)
        assert_false(archived_from_url)

    @mock.patch('website.archiver.tasks.archive')
    def test_copied_from_id_trashed(self, mock_archive):
        file_node = self.get_test_file()
        second_file_node = self.get_second_test_file()
        file_node.copied_from = second_file_node
        self.project.register_node(
            schema=get_default_metaschema(),
            auth=Auth(self.user),
            data=None,
        )
        trashed_node = second_file_node.delete()
        assert_false(trashed_node.copied_from)
Example #13
0
class TestS3ViewsConfig(OsfTestCase):
    def setUp(self):

        super(TestS3ViewsConfig, 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()
        self.node_url = '/api/v1/project/{0}/'.format(self.project._id)

    @mock.patch('website.addons.s3.views.config.does_bucket_exist')
    @mock.patch('website.addons.s3.views.config.adjust_cors')
    def test_s3_settings_no_bucket(self, mock_cors, mock_does_bucket_exist):
        mock_does_bucket_exist.return_value = False
        mock_cors.return_value = True
        url = self.project.api_url + 's3/settings/'
        rv = self.app.post_json(url, {},
                                expect_errors=True,
                                auth=self.user.auth)
        assert_true('trouble' in rv.body)

    @mock.patch('website.addons.s3.views.config.does_bucket_exist')
    @mock.patch('website.addons.s3.views.config.adjust_cors')
    def test_s3_set_bucket(self, mock_cors, mock_exist):

        mock_cors.return_value = True
        mock_exist.return_value = True

        url = self.project.api_url + 's3/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 + 's3/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 + 's3/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 + 's3/settings/'
        res = self.app.post_json(url, {'s3_bucket': 'hammertofall'},
                                 auth=user.auth,
                                 expect_errors=True)
        assert_equal(res.status_code, http.BAD_REQUEST)

    @mock.patch('website.addons.s3.api.S3Wrapper.from_addon')
    def test_s3_set_bucket_registered(self, mock_from_addon):

        mock_from_addon.return_value = create_mock_wrapper()

        registration = self.project.register_node(None, self.consolidated_auth,
                                                  '', '')

        url = registration.api_url + 's3/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.has_access')
    @mock.patch('website.addons.s3.views.config.create_osf_user')
    def test_user_settings(self, mock_user, mock_access):
        mock_access.return_value = True
        mock_user.return_value = ('osf-user-12345', {
            'access_key_id': 'scout',
            'secret_access_key': 'ssshhhhhhhhh'
        })
        url = '/api/v1/settings/s3/'
        self.app.post_json(url, {
            'access_key': 'scout',
            'secret_key': 'Atticus'
        },
                           auth=self.user.auth)
        self.user_settings.reload()
        assert_equals(self.user_settings.access_key, 'scout')

    @mock.patch('website.addons.s3.model.AddonS3UserSettings.remove_iam_user')
    def test_s3_remove_user_settings(self, mock_access):
        mock_access.return_value = True
        self.user_settings.access_key = 'to-kill-a-mocking-bucket'
        self.user_settings.secret_key = 'itsasecret'
        self.user_settings.save()
        url = '/api/v1/settings/s3/'
        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)
        assert_equals(mock_access.call_count, 1)

    @mock.patch('website.addons.s3.model.AddonS3UserSettings.remove_iam_user')
    def test_s3_remove_user_settings_none(self, mock_access):
        self.user_settings.access_key = None
        self.user_settings.secret_key = None
        self.user_settings.save()
        url = '/api/v1/settings/s3/'
        self.app.delete(url, auth=self.user.auth)
        self.user_settings.reload()
        assert_equals(mock_access.call_count, 0)

    @mock.patch('website.addons.s3.views.config.has_access')
    def test_user_settings_no_auth(self, mock_access):
        mock_access.return_value = False
        url = '/api/v1/settings/s3/'
        rv = self.app.post_json(url, {},
                                auth=self.user.auth,
                                expect_errors=True)
        assert_equals(rv.status_int, http.BAD_REQUEST)

    @mock.patch('website.addons.s3.views.config.has_access')
    @mock.patch('website.addons.s3.views.config.create_osf_user')
    def test_node_settings_no_user_settings(self, mock_user, mock_access):
        self.node_settings.user_settings = None
        self.node_settings.save()
        url = self.node_url + 's3/authorize/'

        mock_access.return_value = True
        mock_user.return_value = ('osf-user-12345', {
            'access_key_id': 'scout',
            'secret_access_key': 'ssshhhhhhhhh'
        })
        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')

    def test_node_settings_no_user_settings_ui(self):
        self.node_settings.user_settings.access_key = None
        self.node_settings.user_settings = None
        self.node_settings.save()
        url = self.project.url + 'settings/'
        rv = self.app.get(url, auth=self.user.auth)
        assert_true('<label for="s3Addon">Access Key</label>' in rv.body)

    @mock.patch('website.addons.s3.model.get_bucket_drop_down')
    def test_node_settings_user_settings_ui(self, mock_dropdown):
        mock_dropdown.return_value = ['mybucket']
        url = self.project.url + 'settings/'
        rv = self.app.get(url, auth=self.user.auth)
        assert_true('mybucket' in rv.body)
Example #14
0
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)
Example #15
0
class TestCallbacks(OsfTestCase):
    def setUp(self):

        super(TestCallbacks, 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 = 'singlefile'
        self.node_settings.save()

    def test_update_fields_project(self):
        num_logs = len(self.project.logs)
        # try updating fields
        newfields = {'type': 'project', 'id': '313131', 'name': 'A PROJECT'}
        self.node_settings.update_fields(newfields, self.project,
                                         Auth(self.project.creator))
        #check for updated
        assert_equals(self.node_settings.figshare_id, '313131')
        assert_equals(self.node_settings.figshare_type, 'project')
        assert_equals(self.node_settings.figshare_title, 'A PROJECT')
        # check for log added
        assert_equals(len(self.project.logs), num_logs + 1)

    def test_update_fields_fileset(self):
        num_logs = len(self.project.logs)
        # try updating fields
        newfields = {'type': 'fileset', 'id': '313131', 'name': 'A FILESET'}
        self.node_settings.update_fields(newfields, self.project,
                                         Auth(self.project.creator))
        #check for updated
        assert_equals(self.node_settings.figshare_id, '313131')
        assert_equals(self.node_settings.figshare_type, 'fileset')
        assert_equals(self.node_settings.figshare_title, 'A FILESET')
        # check for log added
        assert_equals(len(self.project.logs), num_logs + 1)

    def test_update_fields_some_missing(self):
        num_logs = len(self.project.logs)
        # try updating fields
        newfields = {'type': 'project', 'id': '313131', 'name': 'A PROJECT'}
        self.node_settings.update_fields(newfields, self.project,
                                         Auth(self.project.creator))
        #check for updated
        assert_equals(self.node_settings.figshare_id, '313131')
        assert_equals(self.node_settings.figshare_title, 'A PROJECT')
        # check for log added
        assert_equals(len(self.project.logs), num_logs + 1)

    def test_update_fields_invalid(self):
        num_logs = len(self.project.logs)
        # try updating fields
        newfields = {
            'adad': 131313,
            'i1513': '313131',
            'titladad': 'A PROJECT'
        }
        self.node_settings.update_fields(newfields, self.project,
                                         Auth(self.project.creator))
        #check for updated
        assert_equals(self.node_settings.figshare_id, '123456')
        assert_equals(self.node_settings.figshare_type, 'project')
        assert_equals(self.node_settings.figshare_title, 'singlefile')
        # check for log added
        assert_equals(len(self.project.logs), num_logs)

    def test_api_url_no_user(self):
        self.node_settings.user_settings = None
        self.node_settings.save()
        assert_equal(self.node_settings.api_url, figshare_settings.API_URL)

    def test_api_url(self):
        assert_equal(self.node_settings.api_url,
                     figshare_settings.API_OAUTH_URL)

    def test_before_register_linked_content(self):
        assert_false(
            self.node_settings.before_register(self.project,
                                               self.project.creator) is None)

    def test_before_register_no_linked_content(self):
        self.node_settings.figshare_id = None
        assert_true(
            self.node_settings.before_register(self.project,
                                               self.project.creator) is None)

    def test_before_remove_contributor_authenticator(self):
        message = self.node_settings.before_remove_contributor(
            self.project, self.project.creator)
        assert_true(message)

    def test_before_remove_contributor_not_authenticator(self):
        message = self.node_settings.before_remove_contributor(
            self.project, self.non_authenticator)
        assert_false(message)

    def test_after_remove_contributor_authenticator_not_self(self):
        auth = Auth(user=self.non_authenticator)
        msg = self.node_settings.after_remove_contributor(
            self.project, self.project.creator, auth)

        assert_in(self.project.project_or_component, msg)
        assert_equal(self.node_settings.user_settings, None)
        assert_in("You can re-authenticate", msg)

    def test_after_remove_contributor_authenticator_self(self):
        msg = self.node_settings.after_remove_contributor(
            self.project, self.project.creator, self.consolidated_auth)

        assert_in(self.project.title, msg)
        assert_equal(self.node_settings.user_settings, None)
        assert_not_in("You can re-authenticate", msg)

    def test_after_fork_authenticator(self):
        fork = ProjectFactory()
        clone, message = self.node_settings.after_fork(
            self.project,
            fork,
            self.project.creator,
        )
        assert_equal(
            self.node_settings.user_settings,
            clone.user_settings,
        )

    def test_after_fork_not_authenticator(self):
        fork = ProjectFactory()
        clone, message = self.node_settings.after_fork(
            self.project,
            fork,
            self.non_authenticator,
        )
        assert_equal(
            clone.user_settings,
            None,
        )

    def test_after_delete(self):
        self.project.remove_node(Auth(user=self.project.creator))
        # Ensure that changes to node settings have been saved
        self.node_settings.reload()
        assert_true(self.node_settings.user_settings is None)
        assert_true(self.node_settings.figshare_id is None)
        assert_true(self.node_settings.figshare_type is None)
        assert_true(self.node_settings.figshare_title is None)

    def test_does_not_get_copied_to_registrations(self):
        registration = self.project.register_node(
            schema=None,
            auth=Auth(user=self.project.creator),
            template='Template1',
            data='hodor')
        assert_false(registration.has_addon('figshare'))
Example #16
0
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)
Example #17
0
class TestAddonFileViews(OsfTestCase):
    @classmethod
    def setUpClass(cls):
        super(TestAddonFileViews, cls).setUpClass()
        PROVIDER_MAP["github"] = [TestFolder, TestFile, TestFileNode]
        TestFileNode.provider = "github"

    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 = GitHubAccountFactory()
        self.oauth.save()

        self.user.external_accounts.append(self.oauth)
        self.user.save()

        self.node_addon.user_settings = self.user_addon
        self.node_addon.external_account = self.oauth
        self.node_addon.repo = "Truth"
        self.node_addon.user = "******"
        self.node_addon.save()

    @classmethod
    def tearDownClass(cls):
        super(TestAddonFileViews, cls).tearDownClass()
        PROVIDER_MAP["github"] = [models.GithubFolder, models.GithubFile, models.GithubFileNode]
        del PROVIDER_MAP["test_addons"]
        TrashedFileNode.remove()

    def get_test_file(self):
        version = models.FileVersion(identifier="1")
        version.save()
        versions = [version]
        ret = TestFile(
            name="Test", node=self.project, path="/test/Test", materialized_path="/test/Test", versions=versions
        )
        ret.save()
        return ret

    def get_second_test_file(self):
        version = models.FileVersion(identifier="1")
        version.save()
        ret = TestFile(
            name="Test2", node=self.project, path="/test/Test2", materialized_path="/test/Test2", versions=[version]
        )
        ret.save()
        return ret

    def get_mako_return(self):
        ret = serialize_node(self.project, Auth(self.user), primary=True)
        ret.update(
            {
                "error": "",
                "provider": "",
                "file_path": "",
                "sharejs_uuid": "",
                "private": "",
                "urls": {
                    "files": "",
                    "render": "",
                    "sharejs": "",
                    "mfr": "",
                    "gravatar": "",
                    "external": "",
                    "archived_from": "",
                },
                "size": "",
                "extra": "",
                "file_name": "",
                "materialized_path": "",
                "file_id": "",
            }
        )
        ret.update(rubeus.collect_addon_assets(self.project))
        return ret

    def test_redirects_to_guid(self):
        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        resp = self.app.get(
            self.project.web_url_for("addon_view_or_download_file", path=file_node.path.strip("/"), provider="github"),
            auth=self.user.auth,
        )

        assert_equals(resp.status_code, 302)
        assert_equals(resp.location, "http://*****:*****@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()

        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        mock_view_file.return_value = self.get_mako_return()

        self.app.get("/{}/?action=view".format(guid._id), auth=self.user.auth)

        args, kwargs = mock_view_file.call_args
        assert_equals(kwargs, {})
        assert_equals(args[0].user._id, self.user._id)
        assert_equals(args[1], self.project)
        assert_equals(args[2], file_node)
        assert_true(isinstance(args[3], file_node.touch(None).__class__))

    @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()

        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        mock_view_file.return_value = self.get_mako_return()

        self.app.get("/{}/".format(guid._id), auth=self.user.auth)

        args, kwargs = mock_view_file.call_args
        assert_equals(kwargs, {})
        assert_equals(args[0].user._id, self.user._id)
        assert_equals(args[1], self.project)
        assert_equals(args[2], file_node)
        assert_true(isinstance(args[3], file_node.touch(None).__class__))

    def test_download_create_guid(self):
        file_node = self.get_test_file()
        assert_is(file_node.get_guid(), None)

        self.app.get(
            self.project.web_url_for("addon_view_or_download_file", path=file_node.path.strip("/"), provider="github"),
            auth=self.user.auth,
        )

        assert_true(file_node.get_guid())

    def test_view_file_does_not_delete_file_when_requesting_invalid_version(self):
        with mock.patch(
            "website.addons.github.model.GitHubNodeSettings.is_private", new_callable=mock.PropertyMock
        ) as mock_is_private:
            mock_is_private.return_value = False

            file_node = self.get_test_file()
            assert_is(file_node.get_guid(), None)

            url = self.project.web_url_for(
                "addon_view_or_download_file", path=file_node.path.strip("/"), provider="github"
            )
            # First view generated GUID
            self.app.get(url, auth=self.user.auth)

            self.app.get(url + "?version=invalid", auth=self.user.auth, expect_errors=True)

            assert_is_not_none(StoredFileNode.load(file_node._id))
            assert_is_none(TrashedFileNode.load(file_node._id))

    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, 401)

    def test_nonstorage_addons_raise(self):
        resp = self.app.get(
            self.project.web_url_for(
                "addon_view_or_download_file", path="sillywiki", provider="wiki", action="download"
            ),
            auth=self.user.auth,
            expect_errors=True,
        )

        assert_equals(resp.status_code, 400)

    def test_head_returns_url(self):
        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        resp = self.app.head("/{}/".format(guid._id), auth=self.user.auth)
        location = furl.furl(resp.location)
        assert_urls_equal(location.url, file_node.generate_waterbutler_url(direct=None, version=None))

    def test_head_returns_url_with_version(self):
        file_node = self.get_test_file()
        guid = file_node.get_guid(create=True)

        resp = self.app.head("/{}/?revision=1&foo=bar".format(guid._id), auth=self.user.auth)
        location = furl.furl(resp.location)
        # Note: version is added but us but all other url params are added as well
        assert_urls_equal(
            location.url, file_node.generate_waterbutler_url(direct=None, revision=1, version=None, foo="bar")
        )

    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.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, 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.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, 401)

    def test_delete_action_creates_trashed_file_node(self):
        file_node = self.get_test_file()
        payload = {"provider": file_node.provider, "metadata": {"path": "/test/Test", "materialized": "/test/Test"}}
        views.addon_delete_file_node(
            self=None, node=self.project, user=self.user, event_type="file_removed", payload=payload
        )
        assert_false(StoredFileNode.load(file_node._id))
        assert_true(TrashedFileNode.load(file_node._id))

    def test_delete_action_for_folder_deletes_subfolders_and_creates_trashed_file_nodes(self):
        file_node = self.get_test_file()
        subfolder = TestFolder(
            name="folder", node=self.project, path="/test/folder/", materialized_path="/test/folder/", versions=[]
        )
        subfolder.save()
        payload = {"provider": file_node.provider, "metadata": {"path": "/test/", "materialized": "/test/"}}
        views.addon_delete_file_node(
            self=None, node=self.project, user=self.user, event_type="file_removed", payload=payload
        )
        assert_false(StoredFileNode.load(file_node._id))
        assert_true(TrashedFileNode.load(file_node._id))
        assert_false(StoredFileNode.load(subfolder._id))

    @mock.patch("website.archiver.tasks.archive")
    def test_archived_from_url(self, mock_archive):
        file_node = self.get_test_file()
        second_file_node = self.get_second_test_file()
        file_node.copied_from = second_file_node

        registered_node = self.project.register_node(schema=get_default_metaschema(), auth=Auth(self.user), data=None)

        archived_from_url = views.get_archived_from_url(registered_node, file_node)
        view_url = self.project.web_url_for(
            "addon_view_or_download_file", provider=file_node.provider, path=file_node.copied_from._id
        )
        assert_true(archived_from_url)
        assert_urls_equal(archived_from_url, view_url)

    @mock.patch("website.archiver.tasks.archive")
    def test_archived_from_url_without_copied_from(self, mock_archive):
        file_node = self.get_test_file()

        registered_node = self.project.register_node(schema=get_default_metaschema(), auth=Auth(self.user), data=None)
        archived_from_url = views.get_archived_from_url(registered_node, file_node)
        assert_false(archived_from_url)

    @mock.patch("website.archiver.tasks.archive")
    def test_copied_from_id_trashed(self, mock_archive):
        file_node = self.get_test_file()
        second_file_node = self.get_second_test_file()
        file_node.copied_from = second_file_node
        self.project.register_node(schema=get_default_metaschema(), auth=Auth(self.user), data=None)
        trashed_node = second_file_node.delete()
        assert_false(trashed_node.copied_from)