예제 #1
0
class TarDownloadTestCase(TestCase):
    def setUp(self):
        # create user
        self.testuser = User(username="******")
        self.testuser.save()

        # create test experiment
        self.exp = Experiment(
            title="tar download test" * 15, created_by=self.testuser, public_access=Experiment.PUBLIC_ACCESS_FULL
        )
        self.exp.save()

        # create test dataset
        self.ds = self.exp.datasets.create(description="testing tar download dataset")

        datafile_content = "\n".join(["some data %d" % i for i in range(1000)])
        filesize = len(datafile_content)
        md5sum = hashlib.md5(datafile_content).hexdigest()
        # create test datafiles and datafile objects
        self.dfs = []
        for i in range(20):
            df = self.ds.datafile_set.create(
                filename="testfile%d.txt" % i,
                mimetype="text/plain",
                size=filesize,
                md5sum=md5sum,
                directory="/".join(["testdir%d" % i for i in range(i, i + 4)]),
            )
            df.file_object = StringIO(datafile_content)
            df.refresh_from_db()
            self.dfs.append(df)

        # mock client
        self.client = Client()

    def tearDown(self):
        # delete created objects and files

        [ds.delete() for ds in self.exp.datasets.all()]
        self.exp.delete()

    def test_tar_experiment_download(self):
        self.assertTrue(all(df.verified for df in self.dfs))
        response = self.client.get(
            reverse("tardis.tardis_portal.download.streaming_download_experiment", args=(self.exp.id, "tar"))
        )
        with NamedTemporaryFile("w") as tarfile:
            for c in response.streaming_content:
                tarfile.write(c)
            tarfile.flush()
            self.assertEqual(int(response["Content-Length"]), os.stat(tarfile.name).st_size)
            tf = TarFile(tarfile.name)
            for df in self.dfs:
                full_path = os.path.join(
                    self.exp.title.replace(" ", "_"), self.ds.description, df.directory, df.filename
                )
                tf.extract(full_path, "/tmp")
                self.assertEqual(os.stat(os.path.join("/tmp", full_path)).st_size, int(df.size))
예제 #2
0
class ViewTemplateContextsTest(TestCase):
    def setUp(self):
        """
        setting up essential objects, copied from tests above
        """

        user = '******'
        pwd = 'secret'
        email = ''
        self.user = User.objects.create_user(user, email, pwd)
        self.userProfile = self.user.userprofile
        self.exp = Experiment(title='test exp1',
                              institution_name='monash',
                              created_by=self.user)
        self.exp.save()
        self.acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user.id),
            content_object=self.exp,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
        )
        self.acl.save()
        self.dataset = Dataset(description='dataset description...')
        self.dataset.save()
        self.dataset.experiments.add(self.exp)
        self.dataset.save()

        self.datafile = DataFile(dataset=self.dataset,
                                 size=42,
                                 filename="foo",
                                 md5sum="junk")
        self.datafile.save()

    def tearDown(self):
        self.user.delete()
        self.exp.delete()
        self.dataset.delete()
        self.datafile.delete()
        self.acl.delete()

    def testExperimentView(self):
        """
        test some template context parameters for an experiment view
        """
        from tardis.tardis_portal.views import ExperimentView
        from django.http import HttpRequest
        import sys

        # Default behavior
        views_module = flexmock(sys.modules['tardis.tardis_portal.views'])
        request = HttpRequest()
        request.method = 'GET'
        request.user = self.user
        request.groups = []
        context = {
            'organization': ['test', 'test2'],
            'default_organization':
            'test',
            'default_format':
            'tar',
            'protocol': [['tgz', '/download/experiment/1/tgz/'],
                         ['tar', '/download/experiment/1/tar/']]
        }
        views_module.should_call('render_response_index'). \
            with_args(_AnyMatcher(), "tardis_portal/view_experiment.html",
                      _ContextMatcher(context))
        view_fn = ExperimentView.as_view()
        response = view_fn(request, experiment_id=self.exp.id)
        self.assertEqual(response.status_code, 200)

        # Behavior with USER_AGENT_SENSING enabled and a request.user_agent
        saved_setting = getattr(settings, "USER_AGENT_SENSING", None)
        try:
            setattr(settings, "USER_AGENT_SENSING", True)
            request = HttpRequest()
            request.method = 'GET'
            request.user = self.user
            request.groups = []
            mock_agent = _MiniMock(os=_MiniMock(family="Macintosh"))
            setattr(request, 'user_agent', mock_agent)
            context = {
                'organization': ['classic', 'test', 'test2'],
                'default_organization': 'classic',
                'default_format': 'tar',
                'protocol': [['tar', '/download/experiment/1/tar/']]
            }
            views_module.should_call('render_response_index'). \
                with_args(_AnyMatcher(), "tardis_portal/view_experiment.html",
                          _ContextMatcher(context))
            view_fn = ExperimentView.as_view()
            response = view_fn(request, experiment_id=self.exp.id)
            self.assertEqual(response.status_code, 200)
        finally:
            if saved_setting is not None:
                setattr(settings, "USER_AGENT_SENSING", saved_setting)
            else:
                delattr(settings, "USER_AGENT_SENSING")

    def testDatasetView(self):
        """
        test some context parameters for a dataset view
        """
        from tardis.tardis_portal.views import DatasetView
        from django.http import HttpRequest
        import sys

        views_module = flexmock(sys.modules['tardis.tardis_portal.views'])
        request = HttpRequest()
        request.method = 'GET'
        request.user = self.user
        request.groups = []
        context = {'default_organization': 'test', 'default_format': 'tar'}
        views_module.should_call('render_response_index'). \
            with_args(_AnyMatcher(), "tardis_portal/view_dataset.html",
                      _ContextMatcher(context))
        view_fn = DatasetView.as_view()
        response = view_fn(request, dataset_id=self.dataset.id)
        self.assertEqual(response.status_code, 200)

        # Behavior with USER_AGENT_SENSING enabled and a request.user_agent
        saved_setting = getattr(settings, "USER_AGENT_SENSING", None)
        try:
            setattr(settings, "USER_AGENT_SENSING", True)
            request = HttpRequest()
            request.method = 'GET'
            request.user = self.user
            request.groups = []
            mock_agent = _MiniMock(os=_MiniMock(family="Macintosh"))
            setattr(request, 'user_agent', mock_agent)
            context = {
                'default_organization': 'classic',
                'default_format': 'tar'
            }
            views_module.should_call('render_response_index'). \
                with_args(_AnyMatcher(), "tardis_portal/view_dataset.html",
                          _ContextMatcher(context))
            view_fn = DatasetView.as_view()
            response = view_fn(request, dataset_id=self.dataset.id)
            self.assertEqual(response.status_code, 200)
        finally:
            if saved_setting is not None:
                setattr(settings, "USER_AGENT_SENSING", saved_setting)
            else:
                delattr(settings, "USER_AGENT_SENSING")
예제 #3
0
class ContextualViewTest(TestCase):
    def setUp(self):
        """
        setting up essential objects, copied from tests above
        """
        user = '******'
        pwd = 'secret'
        email = ''
        self.user = User.objects.create_user(user, email, pwd)
        self.userProfile = self.user.userprofile
        self.exp = Experiment(title='test exp1',
                              institution_name='monash',
                              created_by=self.user)
        self.exp.save()
        self.acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user.id),
            content_object=self.exp,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
        )
        self.acl.save()
        self.dataset = Dataset(description='dataset description...')
        self.dataset.save()
        self.dataset.experiments.add(self.exp)
        self.dataset.save()

        self.datafile = DataFile(dataset=self.dataset,
                                 size=42,
                                 filename="foo",
                                 md5sum="junk")
        self.datafile.save()

        self.testschema = Schema(namespace="http://test.com/test/schema",
                                 name="Test View",
                                 type=Schema.DATAFILE,
                                 hidden=True)
        self.testschema.save()
        self.dfps = DatafileParameterSet(datafile=self.datafile,
                                         schema=self.testschema)
        self.dfps.save()

    def tearDown(self):
        self.user.delete()
        self.exp.delete()
        self.dataset.delete()
        self.datafile.delete()
        self.testschema.delete()
        self.dfps.delete()
        self.acl.delete()

    def testDetailsDisplay(self):
        """
        test display of view for an existing schema and no display for an
        undefined one.
        """
        from tardis.tardis_portal.views import display_datafile_details
        request = flexmock(user=self.user, groups=[("testgroup", flexmock())])
        with self.settings(DATAFILE_VIEWS=[(
                "http://test.com/test/schema",
                "/test/url"), ("http://does.not.exist", "/false/url")]):
            response = display_datafile_details(request,
                                                datafile_id=self.datafile.id)
            self.assertEqual(response.status_code, 200)
            self.assertTrue("/ajax/parameters/" in response.content)
            self.assertTrue("/test/url" in response.content)
            self.assertFalse("/false/url" in response.content)
예제 #4
0
class DownloadTestCase(TestCase):

    def setUp(self):
        # create a test user
        self.user = User.objects.create_user(username='******',
                                             email='',
                                             password='******')

        # create a public experiment
        self.experiment1 = Experiment(
            title='Experiment 1',
            created_by=self.user,
            public_access=Experiment.PUBLIC_ACCESS_FULL)
        self.experiment1.save()

        # create a non-public experiment
        self.experiment2 = Experiment(
            title='Experiment 2',
            created_by=self.user,
            public_access=Experiment.PUBLIC_ACCESS_NONE)
        self.experiment2.save()

        # dataset1 belongs to experiment1
        self.dataset1 = Dataset(description='dangerous;name')
        self.dataset1.save()
        self.dataset1.experiments.add(self.experiment1)
        self.dataset1.save()

        # dataset2 belongs to experiment2
        self.dataset2 = Dataset(description='terrible\nname')
        self.dataset2.save()
        self.dataset2.experiments.add(self.experiment2)
        self.dataset2.save()

        # absolute path first
        filename1 = 'testfile.txt'
        filename2 = 'testfile.tiff'
        self.dest1 = abspath(join(settings.FILE_STORE_PATH, '%s/%s/'
                                  % (self.experiment1.id,
                                     self.dataset1.id)))
        self.dest2 = abspath(join(settings.FILE_STORE_PATH,
                                  '%s/%s/'
                                  % (self.experiment2.id,
                                     self.dataset2.id)))
        if not exists(self.dest1):
            makedirs(self.dest1)
        if not exists(self.dest2):
            makedirs(self.dest2)

        testfile1 = abspath(join(self.dest1, filename1))
        f = open(testfile1, 'w')
        f.write("Hello World!\n")
        f.close()

        testfile2 = abspath(join(self.dest2, filename2))
        _generate_test_image(testfile2)

        self.datafile1 = self._build_datafile(testfile1, filename1,
                                              self.dataset1)

        self.datafile2 = self._build_datafile(testfile2, filename2,
                                              self.dataset2)

    def _build_datafile(self, testfile, filename, dataset, checksum=None,
                        size=None, mimetype=''):
        filesize, sha512sum = get_size_and_sha512sum(testfile)
        datafile = DataFile(dataset=dataset, filename=filename,
                            mimetype=mimetype,
                            size=size if size is not None else filesize,
                            sha512sum=(checksum if checksum else sha512sum))
        datafile.save()
        dfo = DataFileObject(
            datafile=datafile,
            storage_box=datafile.get_default_storage_box())
        dfo.save()
        with open(testfile, 'r') as sourcefile:
            dfo.file_object = sourcefile
        return DataFile.objects.get(pk=datafile.pk)

    def tearDown(self):
        self.user.delete()
        self.experiment1.delete()
        self.experiment2.delete()
        rmtree(self.dest1)
        rmtree(self.dest2)

    def testView(self):
        client = Client()

        # check view of file1
        response = client.get('/datafile/view/%i/' % self.datafile1.id)

        self.assertEqual(response['Content-Disposition'],
                         'inline; filename="%s"'
                         % self.datafile1.filename)
        self.assertEqual(response.status_code, 200)
        response_content = ""
        for c in response.streaming_content:
            response_content += c
        self.assertEqual(response_content, 'Hello World!\n')

        # check view of file2
        response = client.get('/datafile/view/%i/' % self.datafile2.id)
        # Should be forbidden
        self.assertEqual(response.status_code, 403)

        self.experiment2.public_access = Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        # check view of file2 again
        response = client.get('/datafile/view/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 200)

        # The following behaviour relies on ImageMagick
        if IMAGEMAGICK_AVAILABLE:
            # file2 should have a ".png" filename
            self.assertEqual(response['Content-Disposition'],
                             'inline; filename="%s"'
                             % (self.datafile2.filename+'.png'))
            # file2 should be a PNG
            self.assertEqual(response['Content-Type'], 'image/png')
            png_signature = "\x89PNG\r\n\x1a\n"
            self.assertEqual(response.content[0:8], png_signature)
        else:
            # file2 should have a ".tiff" filename
            self.assertEqual(response['Content-Disposition'],
                             'inline; filename="%s"'
                             % (self.datafile2.filename))
            # file2 should be a TIFF
            self.assertEqual(response['Content-Type'], 'image/tiff')
            tiff_signature = "II\x2a\x00"
            self.assertEqual(response.content[0:4], tiff_signature)

    def _check_tar_file(self, content, rootdir, datafiles,
                        simpleNames=False, noTxt=False):
        with NamedTemporaryFile('w') as tempfile:
            for c in content:
                tempfile.write(c)
            tempfile.flush()
            if getsize(tempfile.name) > 0:
                expect(is_tarfile(tempfile.name)).to_be_truthy()
                try:
                    tf = TarFile(tempfile.name, 'r')
                    self._check_names(datafiles, tf.getnames(),
                                      rootdir, simpleNames, noTxt)
                finally:
                    tf.close()
            else:
                self._check_names(datafiles, [],
                                  rootdir, simpleNames, noTxt)

    def _check_zip_file(self, content, rootdir, datafiles,
                        simpleNames=False, noTxt=False):
        with NamedTemporaryFile('w') as tempfile:
            for c in content:
                tempfile.write(c)
            tempfile.flush()
            # It should be a zip file
            expect(is_zipfile(tempfile.name)).to_be_truthy()
            try:
                zf = ZipFile(tempfile.name, 'r')
                self._check_names(datafiles, zf.namelist(),
                                  rootdir, simpleNames, noTxt)
            finally:
                zf.close()

    def _check_names(self, datafiles, names, rootdir, simpleNames, noTxt):
        # SimpleNames says if we expect basenames or pathnames
        # NoTxt says if we expect '.txt' files to be filtered out
        for name in names:
            self.assertNotRegexpMatches(name, '\n|;')
        expect(len(names)).to_equal(len(datafiles))

    def testDownload(self):
        client = Client()

        # check download for experiment1 as tar
        response = client.get('/download/experiment/%i/tar/' %
                              self.experiment1.id)
        if settings.EXP_SPACES_TO_UNDERSCORES:
            exp1_title = self.experiment1.title.replace(' ', '_')
        else:
            exp1_title = self.experiment1.title
        exp1_title = quote(exp1_title,
                           safe=settings.SAFE_FILESYSTEM_CHARACTERS)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s-complete.tar"'
                         % exp1_title)
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(
            response.streaming_content, exp1_title,
            reduce(lambda x, y: x + y,
                   [ds.datafile_set.all()
                    for ds in self.experiment1.datasets.all()]))

        # check download of file1
        response = client.get('/download/datafile/%i/' % self.datafile1.id)

        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s"'
                         % self.datafile1.filename)
        self.assertEqual(response.status_code, 200)
        response_content = ""
        for c in response.streaming_content:
            response_content += c
        self.assertEqual(response_content, 'Hello World!\n')

        # requesting file2 should be forbidden...
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 403)

        # check dataset1 download as tar
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [self.dataset1.id],
                                'datafile': [],
                                'comptype': 'tar'})
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(response.streaming_content,
                             'Experiment 1-selection',
                             self.dataset1.datafile_set.all())

        # check dataset2 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [self.dataset2.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 403)

        # check datafile1 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [],
                                'datafile': [self.datafile1.id]})
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(response.streaming_content,
                             'Experiment 1-selection',
                             [self.datafile1])

        # check datafile2 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [],
                                'datafile': [self.datafile2.id]})
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to "metadata only"
        self.experiment2.public_access = Experiment.PUBLIC_ACCESS_METADATA
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        # Metadata-only means "no file access"!
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to public
        self.experiment2.public_access = Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 200)
        # This should be a TIFF (which often starts with "II\x2a\x00")
        self.assertEqual(response['Content-Type'], 'image/tiff')
        response_content = ""
        for c in response.streaming_content:
            response_content += c
        self.assertEqual(response_content[0:4], "II\x2a\x00")

        # check experiment tar download with alternative organization
        response = client.get('/download/experiment/%i/tar/' %
                              self.experiment1.id)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s-complete.tar"'
                         % exp1_title)
        self._check_tar_file(
            response.streaming_content, str(self.experiment1.id),
            reduce(lambda x, y: x + y,
                   [ds.datafile_set.all()
                    for ds in self.experiment1.datasets.all()]),
            simpleNames=True)

        # check experiment1 download with '.txt' filtered out (none left)
        response = client.get('/download/experiment/%i/tar/' %
                              self.experiment1.id)
        self.assertEqual(response.status_code, 200)

        # check experiment2 download with '.txt' filtered out
        if settings.EXP_SPACES_TO_UNDERSCORES:
            exp2_title = self.experiment2.title.replace(' ', '_')
        else:
            exp2_title = self.experiment2.title
        exp2_title = quote(exp2_title,
                           safe=settings.SAFE_FILESYSTEM_CHARACTERS)
        response = client.get('/download/experiment/%i/tar/' %
                              self.experiment2.id)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s-complete.tar"'
                         % exp2_title)
        self._check_tar_file(
            response.streaming_content, str(self.experiment2.id),
            reduce(lambda x, y: x + y,
                   [ds.datafile_set.all()
                    for ds in self.experiment2.datasets.all()]),
            simpleNames=True, noTxt=True)

    def testDatasetFile(self):
        # check registered text file for physical file meta information
        df = DataFile.objects.get(pk=self.datafile1.id)  # skipping test # noqa # pylint: disable=W0101

        try:
            from magic import Magic
            self.assertEqual(df.mimetype, 'text/plain; charset=us-ascii')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(df.size, 13)
        self.assertEqual(df.md5sum, '8ddd8be4b179a529afa5f2ffae4b9858')

        # Now check we can calculate checksums and infer the mime type
        # for a JPG file.
        filename = 'tardis/tardis_portal/tests/test_data/ands-logo-hi-res.jpg'

        dataset = Dataset.objects.get(pk=self.dataset1.id)

        pdf1 = self._build_datafile(filename, basename(filename), dataset)
        self.assertEqual(pdf1.file_objects.get().verify(), True)
        pdf1 = DataFile.objects.get(pk=pdf1.pk)

        try:
            from magic import Magic  # noqa
            self.assertEqual(pdf1.mimetype, 'image/jpeg')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(pdf1.size, 14232)
        self.assertEqual(pdf1.md5sum, 'c450d5126ffe3d14643815204daf1bfb')

        # Now check that we can override the physical file meta information
        # We are setting size/checksums that don't match the actual file, so
        # the
        pdf2 = self._build_datafile(filename, filename, dataset,
                                    checksum=('cf83e1357eefb8bdf1542850d66d800'
                                              '7d620e4050b5715dc83f4a921d36ce9'
                                              'ce47d0d13c5d85f2b0ff8318d2877ee'
                                              'c2f63b931bd47417a81a538327af927'
                                              'da3e'),
                                    size=0,
                                    mimetype=('application/vnd.openxmlformats-'
                                              'officedocument.presentationml.'
                                              'presentation'))
        self.assertEqual(pdf2.size, 0)
        self.assertEqual(pdf2.md5sum, '')
        self.assertEqual(pdf2.file_objects.get().verified, False)
        pdf2 = DataFile.objects.get(pk=pdf2.pk)
        try:
            from magic import Magic  # noqa
            self.assertEqual(pdf2.mimetype, ('application/vnd.openxmlformats-'
                                             'officedocument.presentationml.'
                                             'presentation'))
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(pdf2.size, 0)
        self.assertEqual(pdf2.md5sum, '')

        pdf2.mimetype = ''
        pdf2.save()
        pdf2.file_objects.get().save()
        pdf2 = DataFile.objects.get(pk=pdf2.pk)

        try:
            from magic import Magic  # noqa
            self.assertEqual(pdf2.mimetype, 'application/pdf')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
class ParameterSetManagerTestCase(TestCase):

    def setUp(self):
        from django.contrib.auth.models import User
        from tempfile import mkdtemp

        user = '******'
        pwd = 'secret'
        email = ''
        self.user = User.objects.create_user(user, email, pwd)

        self.test_dir = mkdtemp()

        self.exp = Experiment(title='test exp1',
                              institution_name='monash',
                              created_by=self.user)
        self.exp.save()

        self.dataset = Dataset(description="dataset description...")
        self.dataset.save()
        self.dataset.experiments.add(self.exp)
        self.dataset.save()

        self.datafile = DataFile(dataset=self.dataset,
                                 filename="testfile.txt",
                                 size="42", md5sum='bogus')
        self.datafile.save()

        self.dfo = DataFileObject(
            datafile=self.datafile,
            storage_box=self.datafile.get_default_storage_box(),
            uri="1/testfile.txt")
        self.dfo.save()

        self.schema = Schema(
            namespace="http://localhost/psmtest/df/",
            name="Parameter Set Manager", type=3)
        self.schema.save()

        self.parametername1 = ParameterName(
            schema=self.schema, name="parameter1",
            full_name="Parameter 1")
        self.parametername1.save()

        self.parametername2 = ParameterName(
            schema=self.schema, name="parameter2",
            full_name="Parameter 2",
            data_type=ParameterName.NUMERIC)
        self.parametername2.save()

        self.parametername3 = ParameterName(
            schema=self.schema, name="parameter3",
            full_name="Parameter 3",
            data_type=ParameterName.DATETIME)
        self.parametername3.save()

        self.datafileparameterset = DatafileParameterSet(
            schema=self.schema, datafile=self.datafile)
        self.datafileparameterset.save()

        self.datafileparameter1 = DatafileParameter(
            parameterset=self.datafileparameterset,
            name=self.parametername1, string_value="test1")
        self.datafileparameter1.save()

        self.datafileparameter2 = DatafileParameter(
            parameterset=self.datafileparameterset,
            name=self.parametername2, numerical_value=2)
        self.datafileparameter2.save()

        # Create a ParameterName and Parameter of type LINK to an experiment
        self.parametername_exp_link = ParameterName(
            schema=self.schema, name="exp_link",
            full_name="This parameter is a experiment LINK",
            data_type=ParameterName.LINK)
        self.parametername_exp_link.save()

        self.exp_link_param = DatafileParameter(
            parameterset=self.datafileparameterset,
            name=self.parametername_exp_link)
        exp_url = self.exp.get_absolute_url()  # /experiment/view/1/
        self.exp_link_param.set_value(exp_url)
        self.exp_link_param.save()

        # Create a ParameterName and Parameter of type LINK to a dataset
        self.parametername_dataset_link = ParameterName(
            schema=self.schema, name="dataset_link",
            full_name="This parameter is a dataset LINK",
            data_type=ParameterName.LINK)
        self.parametername_dataset_link.save()

        self.dataset_link_param = DatafileParameter(
            parameterset=self.datafileparameterset,
            name=self.parametername_dataset_link)
        dataset_url = self.dataset.get_absolute_url()  # /dataset/1/
        self.dataset_link_param.set_value(dataset_url)
        self.dataset_link_param.save()

        # Create a ParameterName type LINK to an unresolvable (non-URL)
        # free-text value
        self.parametername_unresolvable_link = ParameterName(
                schema=self.schema, name="freetext_link",
                full_name="This parameter is a non-URL LINK",
                data_type=ParameterName.LINK)
        self.parametername_unresolvable_link.save()

    def tearDown(self):
        self.exp.delete()
        self.user.delete()
        self.parametername1.delete()
        self.parametername2.delete()
        self.parametername3.delete()
        self.parametername_exp_link.delete()
        self.parametername_dataset_link.delete()
        self.parametername_unresolvable_link.delete()
        self.schema.delete()

    def test_existing_parameterset(self):

        psm = ParameterSetManager(parameterset=self.datafileparameterset)

        self.assertTrue(psm.get_schema().namespace ==
                        "http://localhost/psmtest/df/")

        self.assertTrue(psm.get_param("parameter1").string_value == "test1")

        self.assertTrue(psm.get_param("parameter2", True) == 2)

    def test_new_parameterset(self):

        psm = ParameterSetManager(parentObject=self.datafile,
                                  schema="http://localhost/psmtest/df2/")

        self.assertTrue(psm.get_schema().namespace ==
                        "http://localhost/psmtest/df2/")

        psm.set_param("newparam1", "test3", "New Parameter 1")

        self.assertTrue(psm.get_param("newparam1").string_value ==
                        "test3")

        self.assertTrue(psm.get_param("newparam1").name.full_name ==
                        "New Parameter 1")

        psm.new_param("newparam1", "test4")

        self.assertTrue(len(psm.get_params("newparam1", True)) == 2)

        psm.set_param_list("newparam2", ("a", "b", "c", "d"))

        self.assertTrue(len(psm.get_params("newparam2")) == 4)

        psm.set_params_from_dict(
            {"newparam2": "test5", "newparam3": 3})

        self.assertTrue(psm.get_param("newparam2", True) == "test5")

        # the newparam3 gets created and '3' is set to a string_value
        # since once cannot assume that an initial numeric value
        # will imply continuing numeric type for this new param
        self.assertTrue(psm.get_param("newparam3").string_value == '3')

        psm.delete_params("newparam1")

        self.assertTrue(len(psm.get_params("newparam1", True)) == 0)

    def test_link_parameter_type(self):
        """
        Test that Parameter.link_gfk (GenericForeignKey) is correctly
        assigned after using Parameter.set_value(some_url) for a LINK Parameter.
        """
        psm = ParameterSetManager(parameterset=self.datafileparameterset)

        # Check link to experiment
        exp_url = self.exp.get_absolute_url()  # /experiment/view/1/
        self.assertTrue(psm.get_param("exp_link").string_value ==
                        exp_url)

        self.assertTrue(psm.get_param("exp_link").link_id ==
                        self.exp.id)

        exp_ct = ContentType.objects.get(model__iexact="experiment")
        self.assertTrue(psm.get_param("exp_link").link_ct == exp_ct)

        self.assertTrue(psm.get_param("exp_link").link_gfk == self.exp)

        # Check link to dataset
        dataset_url = self.dataset.get_absolute_url()  # /dataset/1/
        self.assertTrue(psm.get_param("dataset_link").string_value ==
                        dataset_url)

        self.assertTrue(psm.get_param("dataset_link").link_id ==
                        self.dataset.id)

        dataset_ct = ContentType.objects.get(model__iexact="dataset")
        self.assertTrue(psm.get_param("dataset_link").link_ct == dataset_ct)

        self.assertTrue(psm.get_param("dataset_link").link_gfk == self.dataset)

    def test_link_parameter_type_extra(self):
        # make a second ParameterSet for testing some variations
        # in URL values
        self.datafileparameterset2 = DatafileParameterSet(
            schema=self.schema, datafile=self.datafile)
        self.datafileparameterset2.save()

        psm = ParameterSetManager(parameterset=self.datafileparameterset2)

        self.dataset_link_param2 = DatafileParameter(
            parameterset=self.datafileparameterset2,
            name=self.parametername_dataset_link)
        # /dataset/1 - no trailing slash
        dataset_url = self.dataset.get_absolute_url()
        self.dataset_link_param2.set_value(dataset_url)
        self.dataset_link_param2.save()

        # Check link_id/link_ct/link_gfk to dataset
        self.assertTrue(psm.get_param("dataset_link").link_id ==
                        self.dataset.id)

        dataset_ct = ContentType.objects.get(model__iexact="dataset")
        self.assertTrue(psm.get_param("dataset_link").link_ct == dataset_ct)

        self.assertTrue(psm.get_param("dataset_link").link_gfk == self.dataset)

        # Test links of the form /api/v1/experiment/<experiment_id>/
        self.exp_link_param2 = DatafileParameter(
            parameterset=self.datafileparameterset2,
            name=self.parametername_exp_link)
        exp_url = '/api/v1/experiment/%s/' % self.exp.id
        self.exp_link_param2.set_value(exp_url)
        self.exp_link_param2.save()

        # Check link_id/link_ct/link_gfk to experiment
        self.assertTrue(psm.get_param("exp_link").link_id ==
                        self.exp.id)

        exp_ct = ContentType.objects.get(model__iexact="experiment")
        self.assertTrue(psm.get_param("exp_link").link_ct == exp_ct)

        self.assertTrue(psm.get_param("exp_link").link_gfk == self.exp)

    def test_unresolvable_link_parameter(self):
        """
        Test that LINK Parameters that can't be resolved to a model (including
        non-URL values) still work.
        """
        self.datafileparameterset3 = DatafileParameterSet(
                schema=self.schema, datafile=self.datafile)
        self.datafileparameterset3.save()

        psm = ParameterSetManager(parameterset=self.datafileparameterset3)

        # Create a Parameter of type LINK to an unresolvable (non-URL)
        # free-text value
        self.freetext_link_param = DatafileParameter(
                parameterset=self.datafileparameterset3,
                name=self.parametername_unresolvable_link)
        self.assertRaises(SuspiciousOperation,
                          lambda: self.freetext_link_param.set_value(
                              "FREETEXT_ID_123"))

    def test_tz_naive_date_handling(self):
        """
        Ensure that dates are handling in a timezone-aware way.
        """
        psm = ParameterSetManager(parameterset=self.datafileparameterset)

        psm.new_param("parameter3", str(datetime(1970, 01, 01, 10, 0, 0)))

        expect(psm.get_param("parameter3", True))\
            .to_equal(datetime(1970, 01, 01, 0, 0, 0, tzinfo=pytz.utc))

    def test_tz_aware_date_handling(self):
        """
        Ensure that dates are handling in a timezone-aware way.
        """
        psm = ParameterSetManager(parameterset=self.datafileparameterset)

        psm.new_param("parameter3",
                      '1970-01-01T08:00:00+08:00')

        expect(psm.get_param("parameter3", True))\
            .to_equal(datetime(1970, 01, 01, 0, 0, 0, tzinfo=pytz.utc))
예제 #6
0
class DownloadTestCase(TestCase):

    def setUp(self):
        # create a test user
        self.user = User.objects.create_user(username='******',
                                             email='',
                                             password='******')

        Location.force_initialize()

        # create a public experiment
        self.experiment1 = Experiment(title='Experiment 1',
                                      created_by=self.user,
                                      public_access=Experiment.PUBLIC_ACCESS_FULL)
        self.experiment1.save()

        # create a non-public experiment
        self.experiment2 = Experiment(title='Experiment 2',
                                      created_by=self.user,
                                      public_access=Experiment.PUBLIC_ACCESS_NONE)
        self.experiment2.save()

        # dataset1 belongs to experiment1
        self.dataset1 = Dataset()
        self.dataset1.save()
        self.dataset1.experiments.add(self.experiment1)
        self.dataset1.save()

        # dataset2 belongs to experiment2
        self.dataset2 = Dataset()
        self.dataset2.save()
        self.dataset2.experiments.add(self.experiment2)
        self.dataset2.save()

        # absolute path first
        filename1 = 'testfile.txt'
        filename2 = 'testfile.tiff'
        self.dest1 = abspath(join(settings.FILE_STORE_PATH, '%s/%s/'
                                  % (self.experiment1.id,
                                  self.dataset1.id)))
        self.dest2 = abspath(join(settings.FILE_STORE_PATH,
                                '%s/%s/'
                                  % (self.experiment2.id,
                                  self.dataset2.id)))
        if not exists(self.dest1):
            makedirs(self.dest1)
        if not exists(self.dest2):
            makedirs(self.dest2)

        testfile1 = abspath(join(self.dest1, filename1))
        f = open(testfile1, 'w')
        f.write("Hello World!\n")
        f.close()

        testfile2 = abspath(join(self.dest2, filename2))
        _generate_test_image(testfile2)

        self.datafile1 = self._build_datafile( \
            testfile1, filename1, self.dataset1,
            '%d/%d/%s' % (self.experiment1.id, self.dataset1.id, filename1))
                          
        self.datafile2 = self._build_datafile( \
            testfile2, filename2, self.dataset2,
            '%d/%d/%s' % (self.experiment2.id, self.dataset2.id, filename2))

    def _build_datafile(self, testfile, filename, dataset, url, 
                        protocol='', checksum=None, size=None, mimetype=''):
        filesize, sha512sum = get_size_and_sha512sum(testfile)
        datafile = Dataset_File(dataset=dataset, filename=filename,
                                mimetype=mimetype,
                                size=str(size if size != None else filesize), 
                                sha512sum=(checksum if checksum else sha512sum))
        datafile.save()
        if urlparse.urlparse(url).scheme == '':
            location = Location.get_location('local')
        else:
            location = Location.get_location_for_url(url)
            if not location:
                location = Location.load_location({
                    'name': filename, 'url': urlparse.urljoin(url, '.'), 
                    'type': 'external', 
                    'priority': 10, 'transfer_provider': 'local'})
        replica = Replica(datafile=datafile, protocol=protocol, url=url,
                          location=location)
        replica.verify()
        replica.save()
        return Dataset_File.objects.get(pk=datafile.pk)

    def tearDown(self):
        self.user.delete()
        self.experiment1.delete()
        self.experiment2.delete()
        rmtree(self.dest1)
        rmtree(self.dest2)

    def testView(self):
        client = Client()

        # check view of file1
        response = client.get('/datafile/view/%i/' % self.datafile1.id)

        self.assertEqual(response['Content-Disposition'],
                         'inline; filename="%s"'
                         % self.datafile1.filename)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Hello World!\n')

        # check view of file2
        response = client.get('/datafile/view/%i/' % self.datafile2.id)
        # Should be forbidden
        self.assertEqual(response.status_code, 403)

        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        # check view of file2 again
        response = client.get('/datafile/view/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 200)

        # The following behaviour relies on ImageMagick
        if IMAGEMAGICK_AVAILABLE:
            # file2 should have a ".png" filename
            self.assertEqual(response['Content-Disposition'],
                             'inline; filename="%s"'
                             % (self.datafile2.filename+'.png'))
            # file2 should be a PNG
            self.assertEqual(response['Content-Type'], 'image/png')
            png_signature = "\x89PNG\r\n\x1a\n"
            self.assertEqual(response.content[0:8], png_signature)
        else:
            # file2 should have a ".tiff" filename
            self.assertEqual(response['Content-Disposition'],
                             'inline; filename="%s"'
                             % (self.datafile2.filename))
            # file2 should be a TIFF
            self.assertEqual(response['Content-Type'], 'image/tiff')
            tiff_signature = "II\x2a\x00"
            self.assertEqual(response.content[0:4], tiff_signature)

    def _check_tar_file(self, content, rootdir, datafiles,
                        simpleNames=False, noTxt=False):
        with NamedTemporaryFile('w') as tempfile:
            tempfile.write(content)
            tempfile.flush()
            if getsize(tempfile.name) > 0:
                expect(is_tarfile(tempfile.name)).to_be_truthy()
                try:
                    tf = TarFile(tempfile.name, 'r')
                    self._check_names(datafiles, tf.getnames(), 
                                      rootdir, simpleNames, noTxt)
                finally:
                    tf.close()
            else:
                self._check_names(datafiles, [], 
                                  rootdir, simpleNames, noTxt)

    def _check_zip_file(self, content, rootdir, datafiles, 
                        simpleNames=False, noTxt=False):
        with NamedTemporaryFile('w') as tempfile:
            tempfile.write(content)
            tempfile.flush()
            # It should be a zip file
            expect(is_zipfile(tempfile.name)).to_be_truthy()
            try:
                zf = ZipFile(tempfile.name, 'r')
                self._check_names(datafiles, zf.namelist(), 
                                  rootdir, simpleNames, noTxt)
            finally:
                zf.close()

    def _check_names(self, datafiles, names, rootdir, simpleNames, noTxt):
        # SimpleNames says if we expect basenames or pathnames
        # NoTxt says if we expect '.txt' files to be filtered out
        if not noTxt:
            expect(len(names)).to_equal(len(datafiles))
        for df in datafiles:
            if simpleNames:
                filename = df.filename
            else:
                filename = join(rootdir, str(df.dataset.id), 
                                df.filename)
            expect(filename in names).to_be(
                not (noTxt and filename.endswith('.txt')))
        

    def testDownload(self):
        client = Client()

        # check download for experiment1
        response = client.get('/download/experiment/%i/zip/' % \
                                  self.experiment1.id)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="experiment%s-complete.zip"'
                         % self.experiment1.id)
        self.assertEqual(response.status_code, 200)
        self._check_zip_file(
            response.content, str(self.experiment1.id),
            reduce(lambda x, y: x + y,
                   [ds.dataset_file_set.all() \
                        for ds in self.experiment1.datasets.all()]))
                   
        # check download for experiment1 as tar
        response = client.get('/download/experiment/%i/tar/' % \
                                  self.experiment1.id)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="experiment%s-complete.tar"'
                         % self.experiment1.id)
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(
            response.content, str(self.experiment1.id),
            reduce(lambda x, y: x + y,
                   [ds.dataset_file_set.all() \
                        for ds in self.experiment1.datasets.all()]))
                   
        # check download of file1
        response = client.get('/download/datafile/%i/' % self.datafile1.id)

        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s"'
                         % self.datafile1.filename)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Hello World!\n')

        # requesting file2 should be forbidden...
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 403)

        # check dataset1 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [self.dataset1.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 200)
        self._check_zip_file(response.content, 'datasets',
                             self.dataset1.dataset_file_set.all())

        # check dataset1 download as tar
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [self.dataset1.id],
                                'datafile': [],
                                'comptype': 'tar'})
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(response.content, 'datasets',
                             self.dataset1.dataset_file_set.all())

        # check dataset2 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [self.dataset2.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 403)

        # check datafile1 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [],
                                'datafile': [self.datafile1.id]})
        self.assertEqual(response.status_code, 200)
        self._check_zip_file(response.content, 'datasets', [self.datafile1])

        # check datafile2 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [],
                                'datafile': [self.datafile2.id]})
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to "metadata only"
        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_METADATA
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        # Metadata-only means "no file access"!
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to public
        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 200)
        # This should be a TIFF (which often starts with "II\x2a\x00")
        self.assertEqual(response['Content-Type'], 'image/tiff')
        self.assertEqual(response.content[0:4], "II\x2a\x00")

        # check experiment zip download with alternative organization
        response = client.get('/download/experiment/%i/zip/test/' % \
                                  self.experiment1.id)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="experiment%s-complete.zip"'
                         % self.experiment1.id)
        self._check_zip_file(
            response.content, str(self.experiment1.id),
            reduce(lambda x, y: x + y,
                   [ds.dataset_file_set.all() \
                        for ds in self.experiment1.datasets.all()]),
            simpleNames=True)

        # check experiment tar download with alternative organization
        response = client.get('/download/experiment/%i/tar/test/' % \
                                  self.experiment1.id)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="experiment%s-complete.tar"'
                         % self.experiment1.id)
        self._check_tar_file(
            response.content, str(self.experiment1.id),
            reduce(lambda x, y: x + y,
                   [ds.dataset_file_set.all() \
                        for ds in self.experiment1.datasets.all()]),
            simpleNames=True)

        # check experiment1 download with '.txt' filtered out (none left)
        response = client.get('/download/experiment/%i/tar/test2/' % \
                                  self.experiment1.id)
        self.assertEqual(response.status_code, 400)

        # check experiment2 download with '.txt' filtered out
        response = client.get('/download/experiment/%i/tar/test2/' % \
                                  self.experiment2.id)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="experiment%s-complete.tar"'
                         % self.experiment2.id)
        self._check_tar_file(
            response.content, str(self.experiment2.id),
            reduce(lambda x, y: x + y,
                   [ds.dataset_file_set.all() \
                        for ds in self.experiment2.datasets.all()]),
            simpleNames=True, noTxt=True)

        # check dataset1 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [self.dataset1.id],
                                'datafile': [],
                                'comptype': 'zip',
                                'organization': 'test'})
        self.assertEqual(response.status_code, 200)
        self._check_zip_file(response.content, 'datasets',
                             self.dataset1.dataset_file_set.all(),
                             simpleNames=True)


    def testDatasetFile(self):

        # check registered text file for physical file meta information
        df = Dataset_File.objects.get(pk=self.datafile1.id)

        try:
            from magic import Magic
            self.assertEqual(df.mimetype, 'text/plain; charset=us-ascii')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(df.size, str(13))
        self.assertEqual(df.md5sum, '8ddd8be4b179a529afa5f2ffae4b9858')

        # Now check we can calculate checksums and infer the mime type
        # for a JPG file.
        filename = abspath(join(dirname(__file__),
                                '../static/images/ands-logo-hi-res.jpg'))

        dataset = Dataset.objects.get(pk=self.dataset1.id)

        pdf1 = self._build_datafile(filename, basename(filename), dataset, 
                                    'file://%s' % filename, protocol='file')
        self.assertEqual(pdf1.get_preferred_replica().verify(), True)
        pdf1 = Dataset_File.objects.get(pk=pdf1.pk)        

        try:
            from magic import Magic
            self.assertEqual(pdf1.mimetype, 'image/jpeg')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(pdf1.size, str(14232))
        self.assertEqual(pdf1.md5sum, 'c450d5126ffe3d14643815204daf1bfb')

        # Now check that we can override the physical file meta information
        # We are setting size/checksums that don't match the actual file, so
        # the 
        pdf2 = self._build_datafile(
            filename, filename, dataset,
            'file://%s' % filename, protocol='file', 
            mimetype='application/vnd.openxmlformats-officedocument.presentationml.presentation',
            size=0,
            # Empty string always has the same hash
            checksum='cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e')
        self.assertEqual(pdf2.size, str(0))
        self.assertEqual(pdf2.md5sum, '')
        self.assertEqual(pdf2.get_preferred_replica().verify(), False)
        pdf2 = Dataset_File.objects.get(pk=pdf2.pk)
        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(pdf2.size, str(0))
        self.assertEqual(pdf2.md5sum, '')

        pdf2.mimetype = ''
        pdf2.save()
        pdf2.get_preferred_replica().save()
        pdf2 = Dataset_File.objects.get(pk=pdf2.pk)

        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/pdf')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
예제 #7
0
class DownloadTestCase(TestCase):

    def setUp(self):
        # create a test user
        self.user = User.objects.create_user(username='******',
                                             email='',
                                             password='******')

        # create a public experiment
        self.experiment1 = Experiment(title='Experiment 1',
                                      created_by=self.user,
                                      public=True)
        self.experiment1.save()

        # create a non-public experiment
        self.experiment2 = Experiment(title='Experiment 2',
                                      created_by=self.user,
                                      public=False)
        self.experiment2.save()

        # dataset1 belongs to experiment1
        self.dataset1 = Dataset(experiment=self.experiment1)
        self.dataset1.save()

        # dataset2 belongs to experiment2
        self.dataset2 = Dataset(experiment=self.experiment2)
        self.dataset2.save()

        # absolute path first
        filename = 'testfile.txt'
        self.dest1 = abspath(join(settings.FILE_STORE_PATH, '%s/%s/'
                                  % (self.experiment1.id,
                                  self.dataset1.id)))
        self.dest2 = abspath(join(settings.FILE_STORE_PATH,
                                '%s/%s/'
                                  % (self.experiment2.id,
                                  self.dataset2.id)))
        if not exists(self.dest1):
            makedirs(self.dest1)
        if not exists(self.dest2):
            makedirs(self.dest2)

        testfile1 = abspath(join(self.dest1, filename))
        f = open(testfile1, 'w')
        f.write("Hello World!\n")
        f.close()

        testfile2 = abspath(join(self.dest2, filename))
        f = open(testfile2, 'w')
        f.write("Hello World!\n")
        f.close()

        self.dataset_file1 = Dataset_File(dataset=self.dataset1,
                                          filename=filename,
                                          protocol='tardis',
                                          url='tardis://%s' % filename)
        self.dataset_file1.save()

        self.dataset_file2 = Dataset_File(dataset=self.dataset2,
                                          filename=basename(filename),
                                          protocol='tardis',
                                          url='tardis://%s' % filename)
        self.dataset_file2.save()

    def tearDown(self):
        self.user.delete()
        self.experiment1.delete()
        self.experiment2.delete()
        rmtree(self.dest1)
        rmtree(self.dest2)

    def testDownload(self):
        client = Client()

        # check download for experiment1
        response = client.get('/download/experiment/%i/zip/' % self.experiment1.id)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="experiment%s-complete.zip"'
                         % self.experiment1.id)
        self.assertEqual(response.status_code, 200)

        # check download of file1
        response = client.get('/download/datafile/%i/' % self.dataset_file1.id)

        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s"'
                         % self.dataset_file2.filename)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Hello World!\n')

        # requesting file2 should be forbidden...
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 403)

        # check dataset1 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [self.dataset1.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 200)

        # check dataset2 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [self.dataset2.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 403)

        # check datafile1 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [],
                                'datafile': [self.dataset_file1.id]})
        self.assertEqual(response.status_code, 200)

        # check datafile2 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [],
                                'datafile': [self.dataset_file2.id]})
        self.assertEqual(response.status_code, 403)

    def testDatasetFile(self):

        # check registered text file for physical file meta information
        df = Dataset_File.objects.get(pk=self.dataset_file1.id)

        try:
            from magic import Magic
            self.assertEqual(df.mimetype, 'text/plain; charset=us-ascii')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(df.size, str(13))
        self.assertEqual(df.md5sum, '8ddd8be4b179a529afa5f2ffae4b9858')

        # now check a pdf file
        filename = join(abspath(dirname(__file__)),
                        '../static/downloads/DatasetDepositionGuide.pdf')

        dataset = Dataset.objects.get(pk=self.dataset1.id)

        pdf1 = Dataset_File(dataset=dataset,
                            filename=basename(filename),
                            url='file://%s' % filename,
                            protocol='file')
        pdf1.save()
        try:
            from magic import Magic
            self.assertEqual(pdf1.mimetype, 'application/pdf')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(pdf1.size, str(1008475))
        self.assertEqual(pdf1.md5sum, '9192b3d3e0056412b1d21d3e33562eba')

        # now check that we can override the physical file meta information
        pdf2 = Dataset_File(dataset=dataset,
                            filename=basename(filename),
                            url='file://%s' % filename,
                            protocol='file',
                            mimetype='application/vnd.openxmlformats-officedocument.presentationml.presentation',
                            size=str(0),
                            md5sum='md5sum')
        pdf2.save()
        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(pdf2.size, str(0))
        self.assertEqual(pdf2.md5sum, 'md5sum')

        pdf2.mimetype = ''
        pdf2.save()

        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/pdf')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
예제 #8
0
class ViewTemplateContextsTest(TestCase):

    def setUp(self):
        """
        setting up essential objects, copied from tests above
        """
        Location.force_initialize()
        self.location = Location.get_location('local')

        user = '******'
        pwd = 'secret'
        email = ''
        self.user = User.objects.create_user(user, email, pwd)
        self.userProfile = UserProfile(user=self.user).save()
        self.exp = Experiment(title='test exp1',
                              institution_name='monash', created_by=self.user)
        self.exp.save()
        self.acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user.id),
            content_object=self.exp,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
        )
        self.acl.save()
        self.dataset = Dataset(description='dataset description...')
        self.dataset.save()
        self.dataset.experiments.add(self.exp)
        self.dataset.save()

        self.dataset_file = Dataset_File(dataset=self.dataset,
                                         size=42, filename="foo",
                                         md5sum="junk")
        self.dataset_file.save()
        self.replica = Replica(datafile=self.dataset_file,
                               url="http://foo",
                               location=self.location,
                               verified=False)
        self.replica.save()

    def tearDown(self):
        self.user.delete()
        self.exp.delete()
        self.dataset.delete()
        self.dataset_file.delete()
        self.acl.delete()

    def testExperimentView(self):
        """
        test some template context parameters for an experiment view
        """
        from tardis.tardis_portal.views import view_experiment
        from tardis.tardis_portal.shortcuts import render_response_index
        from django.http import HttpRequest
        from django.template import Context
        import sys

        # Default behavior
        views_module = flexmock(sys.modules['tardis.tardis_portal.views'])
        request = HttpRequest()
        request.user=self.user
        request.groups=[]
        context = {'organization': ['classic', 'test', 'test2'],
                   'default_organization': 'classic',
                   'default_format': 'zip',
                   'protocol': [['zip', '/download/experiment/1/zip/'],
                                ['tar', '/download/experiment/1/tar/']]}
        views_module.should_call('render_response_index'). \
            with_args(_AnyMatcher(), "tardis_portal/view_experiment.html",
                      _ContextMatcher(context))
        response = view_experiment(request, experiment_id=self.exp.id)
        self.assertEqual(response.status_code, 200)

        # Behavior with USER_AGENT_SENSING enabled and a request.user_agent
        saved_setting = getattr(settings, "USER_AGENT_SENSING", None)
        try:
            setattr(settings, "USER_AGENT_SENSING", True)
            request = HttpRequest()
            request.user=self.user
            request.groups=[]
            mock_agent = _MiniMock(os=_MiniMock(family="Macintosh"))
            setattr(request, 'user_agent', mock_agent);
            context = {'organization': ['classic', 'test', 'test2'],
                       'default_organization': 'classic',
                       'default_format': 'tar',
                       'protocol': [['tar', '/download/experiment/1/tar/']]}
            views_module.should_call('render_response_index'). \
                with_args(_AnyMatcher(), "tardis_portal/view_experiment.html",
                          _ContextMatcher(context))
            response = view_experiment(request, experiment_id=self.exp.id)
            self.assertEqual(response.status_code, 200)
        finally:
            if saved_setting != None:
                setattr(settings, "USER_AGENT_SENSING", saved_setting)
            else:
                delattr(settings, "USER_AGENT_SENSING")


    def testDatasetView(self):
        """
        test some context parameters for a dataset view
        """
        from tardis.tardis_portal.views import view_dataset
        from tardis.tardis_portal.shortcuts import render_response_index
        from django.http import HttpRequest
        from django.template import Context
        import sys

        views_module = flexmock(sys.modules['tardis.tardis_portal.views'])
        request = HttpRequest()
        request.user=self.user
        request.groups=[]
        context = {'default_organization': 'classic',
                   'default_format': 'zip'}
        views_module.should_call('render_response_index'). \
            with_args(_AnyMatcher(), "tardis_portal/view_dataset.html",
                      _ContextMatcher(context))
        response = view_dataset(request, dataset_id=self.dataset.id)
        self.assertEqual(response.status_code, 200)

        # Behavior with USER_AGENT_SENSING enabled and a request.user_agent
        saved_setting = getattr(settings, "USER_AGENT_SENSING", None)
        try:
            setattr(settings, "USER_AGENT_SENSING", True)
            request = HttpRequest()
            request.user=self.user
            request.groups=[]
            mock_agent = _MiniMock(os=_MiniMock(family="Macintosh"))
            setattr(request, 'user_agent', mock_agent);
            context = {'default_organization': 'classic',
                       'default_format': 'tar'}
            views_module.should_call('render_response_index'). \
                with_args(_AnyMatcher(), "tardis_portal/view_dataset.html",
                          _ContextMatcher(context))
            response = view_dataset(request, dataset_id=self.dataset.id)
            self.assertEqual(response.status_code, 200)
        finally:
            if saved_setting != None:
                setattr(settings, "USER_AGENT_SENSING", saved_setting)
            else:
                delattr(settings, "USER_AGENT_SENSING")
class ObjectACLTestCase(TestCase):
    urls = 'tardis.urls'

    def setUp(self):

        # create a couple of test users
        self.user1 = User.objects.create_user('testuser1', '', 'secret')
        self.user2 = User.objects.create_user('testuser2', '', 'secret')
        self.user3 = User.objects.create_user('testuser3', '', 'secret')
        self.user4 = User.objects.create_user('testuser4', '', 'secret')

        # with standard permissions
        for user in [self.user1, self.user2, self.user3, self.user4]:
            user.user_permissions.add(Permission.objects.get(codename='add_experiment'))
            user.user_permissions.add(Permission.objects.get(codename='change_experiment'))
            user.user_permissions.add(Permission.objects.get(codename='change_group'))
            user.user_permissions.add(Permission.objects.get(codename='change_userauthentication'))
            user.user_permissions.add(Permission.objects.get(codename='change_objectacl'))

        self.userProfile1 = self.user1.userprofile
        self.userProfile2 = self.user2.userprofile
        self.userProfile3 = self.user3.userprofile
        self.userProfile4 = self.user4.userprofile

        # each user will have their own client
        self.client1 = Client()
        self.client2 = Client()
        self.client3 = Client()
        self.client4 = Client()

        # user1 will own experiment1
        self.experiment1 = Experiment(
            title='Experiment1',
            institution_name='Australian Synchrotron',
            approved=True,
            public_access=Experiment.PUBLIC_ACCESS_NONE,
            created_by=self.user1,
            )
        self.experiment1.save()

        # user2 will own experiment2
        self.experiment2 = Experiment(
            title='Experiment2',
            institution_name='Australian Synchrotron',
            approved=True,
            public_access=Experiment.PUBLIC_ACCESS_NONE,
            created_by=self.user2,
            )
        self.experiment2.save()

        # experiment3 is public & locked
        self.experiment3 = Experiment(
            title='Experiment3',
            institution_name='Australian Synchrotron',
            approved=True,
            locked=True,
            public_access=Experiment.PUBLIC_ACCESS_FULL,
            created_by=self.user3,
            )
        self.experiment3.save()

        # experiment4 will be accessible based on location information
        self.experiment4 = Experiment(
            title='Experiment4',
            institution_name='Australian Synchrotron',
            approved=True,
            public_access=Experiment.PUBLIC_ACCESS_NONE,
            created_by=self.user1,
            )
        self.experiment4.save()

        # user1 owns experiment1
        acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user1.id),
            content_object=self.experiment1,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
            )
        acl.save()

        # user2 owns experiment2
        acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user2.id),
            content_object=self.experiment2,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
            )
        acl.save()

        # experiment4 is accessible via location
        acl = ObjectACL(
            pluginId='ip_address',
            entityId='127.0.0.1',
            content_object=self.experiment4,
            canRead=True,
            aclOwnershipType=ObjectACL.SYSTEM_OWNED,
        )
        acl.save()

    def tearDown(self):

        self.experiment1.delete()
        self.experiment2.delete()
        self.experiment3.delete()
        self.experiment4.delete()

        self.user1.delete()
        self.user2.delete()
        self.user3.delete()
        self.user4.delete()

        self.client1.logout()
        self.client2.logout()
        self.client3.logout()
        self.client4.logout()

    def testChangeUserPermissions(self):
        login1 = self.client1.login(username=self.user1.username,
                                   password='******')
        self.assertTrue(login1)

        login3 = self.client3.login(username=self.user3.username,
                                   password='******')
        self.assertTrue(login3)

        # user1 should be see experiment1
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user3 should not be able to see experiment1
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # make the group1 a full read/write/owner of the experiment1
        response = self.client1.get('/experiment/control_panel/%i'
                                    '/access_list/add/group/%s/?canRead=true'
                                    '&canWrite=true&canDelete=false&isOwner=true'
                                    % (self.experiment1.id, 'group1'))
        self.assertEqual(response.status_code, 200)

        # ok, now do some tricky stuff
        today = datetime.datetime.today()
        yesterday = today - datetime.timedelta(days=1)
        tomorrow = today + datetime.timedelta(days=1)

        # add user3 to experiment1
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s'
                                    % (self.experiment1.id,
                                       self.user3.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, '<div class="access_list_user')

        # check permissions for user3 - fail as canRead not set to True
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)


        # give user3 read permissions for experiment1 effective TOMORROW
        url = ("/experiment/control_panel/%i/access_list"
               "/change/user/%s/?authMethod=%s")

        response = self.client1.post(url % (self.experiment1.id,
                                            self.user3.username,
                                            localdb_auth_key),
                          {'canRead': True,
                           'effectiveDate_year':  tomorrow.year,
                           'effectiveDate_month': tomorrow.month,
                           'effectiveDate_day':   tomorrow.day,
                           })
        self.assertEqual(response.status_code, 302)

        # check permissions for user3
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # user1 should be see experiment1
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # give user3 read permissions for experiment1 effective YESTERDAY
        url = ("/experiment/control_panel/%i/access_list"
               "/change/user/%s/?authMethod=%s")

        response = self.client1.post(url % (self.experiment1.id,
                                            self.user3.username,
                                            localdb_auth_key),
                          {'canRead': True,
                           'effectiveDate_year':  yesterday.year,
                           'effectiveDate_month': yesterday.month,
                           'effectiveDate_day':   yesterday.day,
                           })
        self.assertEqual(response.status_code, 302)

        # check permissions for user3
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)


    def testReadAccess(self):
        login = self.client1.login(username=self.user1.username,
                                   password='******')
        self.assertTrue(login)

        # user1 should be see experiment1
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user1 should not be allowed to see experiment2
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # user1 should be allowed to see experiment3 as it's public
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user1 should be allowed to see experiment4 based on his IP address
        # response = self.client1.get('/experiment/view/%i/'
        #                            % (self.experiment4.id))
        # self.assertEqual(response.status_code, 200)

        # create a group and add it to experiment1
        response = self.client1.get('/experiment/control_panel'
                                    '/create/group/?group=%s&authMethod=localdb'
                                    % ('group1'))
        self.assertEqual(response.status_code, 200)

        # make the group1 a full read/write/owner of the experiment1
        response = self.client1.get('/experiment/control_panel/%i'
                                    '/access_list/add/group/%s/?canRead=true'
                                    '&canWrite=true&canDelete=false&isOwner=true'
                                    % (self.experiment1.id, 'group1'))
        self.assertEqual(response.status_code, 200)

        # add user2 as admin to the newly created group1
        group = Group.objects.get(name='group1')
        response = self.client1.get('/group/%i/add/%s/?isAdmin=true&authMethod=%s'
                                    % (group.id,
                                       self.user2.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # try it again
        response = self.client1.get('/group/%i/add/%s/?isAdmin=true&authMethod=%s'
                                    % (group.id,
                                       self.user2.username,
                                       localdb_auth_key))
        self.assertEqual(response.content, 'User %s is already member of that'
                         ' group.' % self.user2.username)

        # user1 is not allowed to modify acls for experiment2
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s'
                                    % (self.experiment2.id,
                                       self.user1.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 403)

        # user2 *IS* allowed to modify acls for experiment1, since they are part
        # of an owning group (we add then remove access for user3)
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s'
                                    % (self.experiment1.id,
                                       self.user3.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 200)
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/?authMethod=%s'
                                    % (self.experiment1.id,
                                       self.user3.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'OK')

        # test add non-existent user
        non_existant = 'test_boozer'
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s'
                                    % (self.experiment1.id,
                                       non_existant,
                                       localdb_auth_key))

        self.assertContains(response, 'User %s does not exist' % non_existant)

        # test add to non existant experiment

        # Note: Ideally we'd like to check for error message, but we
        # can't hit it with the decorator in place.  However,
        # currently we check for a 403 (forbidden) error, as the
        # 'experiment_ownership_required' decorator simply checks if
        # the experiment_id appears in the specified user's ACL, and
        # assumes that the absence of the experiment_id means that the
        # experiment exists but the user doesn't have access to
        # it. This could possibly be changed to a 404 error.

        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s' %
                                    (9999, self.user1.username, localdb_auth_key))
        self.assertEqual(response.status_code, 403)

        self.client1.logout()

        # now check user2's permissions
        login = self.client2.login(username=self.user2.username,
                                   password='******')
        self.assertTrue(login)

        # user2 should be able to see experiment1 now
        response = self.client2.get('/experiment/view/%i/'
                                    % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be also able to see experiment2
        response = self.client2.get('/experiment/view/%i/'
                                   % (self.experiment2.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be allowed to see experiment3 as it's public
        response = self.client2.get('/experiment/view/%i/'
                                   % (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be able to add user3 to group1 (experiment1)
        response = self.client2.get(
            '/group/%i/add/%s/?isAdmin=false&authMethod=%s'
            % (group.id, self.user3.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        self.client2.logout()

        # now check user3's permissions
        login = self.client3.login(username=self.user3.username,
                                   password='******')
        self.assertTrue(login)

        # user3 should be able to see experiment1 via his group permissions
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user3 should not be able to see experiment2
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # user3 should be able to see experiment3
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user3 should not be able to add another user4 to group1
        response = self.client3.get(
            '/group/%i/add/%s/?isAdmin=false&authMethod=%s'
            % (group.id, 'testuser4', localdb_auth_key))
        self.assertEqual(response.status_code, 403)

        self.client3.logout()

        # ok, now do some tricky stuff
        today = datetime.datetime.today()
        yesterday = today - datetime.timedelta(days=1)
        tomorrow = today + datetime.timedelta(days=1)

        url = ("/experiment/control_panel/%i/access_list"
               "/change/user/%s/?authMethod=%s")

        login = self.client1.login(username=self.user1.username,
                                   password='******')
        self.assertTrue(login)

        # remove user3 from group1
        response = self.client1.get('/group/%i/remove/%s/'
                                   % (group.id, self.user3.username))
        self.assertEqual(response.status_code, 200)

        # add user3 to experiment1
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s'
                                    % (self.experiment1.id,
                                       self.user3.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, '<div class="access_list_user')

        # give user3 read permissions for experiment1 effective TOMORROW
        response = self.client1.post(url % (self.experiment1.id,
                                            self.user3.username,
                                            localdb_auth_key),
                          {'canRead': True,
                           'effectiveDate_year': tomorrow.year,
                           'effectiveDate_month': tomorrow.month,
                           'effectiveDate_day': tomorrow.day,
                           })
        # logger.debug('[1] response =' + str(response))
        self.assertEqual(response.status_code, 302)

        # check permissions for user3
        login = self.client3.login(username=self.user3.username,
                                   password='******')
        self.assertTrue(login)

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # change effective date to TODAY
        response = self.client1.post(url % (self.experiment1.id,
                                            self.user3.username,
                                            localdb_auth_key),
                          {'canRead': True,
                           'effectiveDate_year': today.year,
                           'effectiveDate_month': today.month,
                           'effectiveDate_day': today.day,
                           })
        self.assertEqual(response.status_code, 302)

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # change effictive date to YESTERDAY
        self.client1.post(url % (self.experiment1.id,
                                 self.user3.username,
                                 localdb_auth_key),
                          {'canRead': True,
                           'effectiveDate_year': yesterday.year,
                           'effectiveDate_month': yesterday.month,
                           'effectiveDate_day': yesterday.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to TOMORROW
        self.client1.post(url % (self.experiment1.id,
                                 self.user3.username,
                                 localdb_auth_key),
                          {'canRead': True,
                           'expiryDate_year': tomorrow.year,
                           'expiryDate_month': tomorrow.month,
                           'expiryDate_day': tomorrow.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to TODAY
        self.client1.post(url % (self.experiment1.id,
                                 self.user3.username,
                                 localdb_auth_key),
                          {'canRead': True,
                           'expiryDate_year': today.year,
                           'expiryDate_month': today.month,
                           'expiryDate_day': today.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to YESTERDAY
        self.client1.post(url % (self.experiment1.id,
                                 self.user3.username,
                                 localdb_auth_key),
                          {'canRead': True,
                           'expiryDate_year': yesterday.year,
                           'expiryDate_month': yesterday.month,
                           'expiryDate_day': yesterday.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # remove user3 from experiment1 again
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/'
                                    % (self.experiment1.id, self.user3.username))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'OK')

        # try again, see if it falls over
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/'
                                    % (self.experiment1.id, self.user3.username))
        self.assertEqual(response.content,
                         'The user %s does not have access to this experiment.'
                         % self.user3.username)

        # try to remove from a non-existant experiment
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/'
                                    % (9999, self.user3.username))
        self.assertEqual(response.status_code, 403)

        # try to remove the only owner
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/'
                                    % (self.experiment1.id, self.user1.username))
        self.assertEqual(response.content, 'All experiments must have at least '
                                           'one user as owner. Add an '
                                           'additional owner first before '
                                           'removing this one.')

        # create a group2 and add it to experiment1
        response = self.client1.get('/experiment/control_panel'
                                    '/create/group/?group=%s&authMethod=localdb'
                                    % ('group2'))
        self.assertEqual(response.status_code, 200)

        # give group2 read-only access to experiment1
        response = self.client1.get('/experiment/control_panel/%i'
                                    '/access_list/add/group/%s/?canRead=true'
                                    '&canWrite=false&canDelete=false&isOwner=false'
                                    % (self.experiment1.id, 'group2'))
        self.assertEqual(response.status_code, 200)

        # add user3 as admin to group2
        self.group2 = Group.objects.get(name='group2')
        response = self.client1.get(
            '/group/%i/add/%s/?isAdmin=true&authMethod=%s'
            % (self.group2.id,
               self.user3.username,
               localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # as user3, try to add myself as an owner of the experiment1
        response = self.client3.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s&canRead=true'
                                    '&canWrite=true&canDelete=false&'
                                    'isOwner=true'
                                    % (self.experiment1.id,
                                       self.user3.username,
                                       localdb_auth_key))
        # this should fail since the group2, of which user3 is a member, is
        # not an 'owner' group, just a read-only group
        self.assertEqual(response.status_code, 403)

        # as user3, attempt to remove user1 as the owner of experiment1
        response = self.client3.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/?authMethod=%s'
                                    % (self.experiment1.id,
                                       self.user1.username,
                                       localdb_auth_key))
        # this should fail since the group2, of which user3 is a member, is
        # not an 'owner' group, just a read-only group
        self.assertEqual(response.status_code, 403)

        # as user1, add user3 as an owner of experiment1
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s&canRead=true'
                                    '&canWrite=true&canDelete=false&'
                                    'isOwner=true'
                                    % (self.experiment1.id,
                                       self.user3.username,
                                       localdb_auth_key))
        # since user1 is an owner user of experiment1, we can add additional
        # owner users to the experiment
        self.assertEqual(response.status_code, 200)

        # as user3 (now an owner), attempt to remove user1 as the owner of
        # experiment1, leaving user3 as the sole owner
        response = self.client3.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/?authMethod=%s'
                                    % (self.experiment1.id,
                                       self.user1.username,
                                       localdb_auth_key))
        # this should now succeed since both user3 and user1 are owners of
        # experiment1, and user3 is allowed to remove other owners (unless they
        # are the only owner user)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'OK')

        # as user3 (now the only owner), attempts to remove myself as the owner
        # of experiment1
        response = self.client3.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/?authMethod=%s'
                                    % (self.experiment1.id,
                                       self.user3.username,
                                       localdb_auth_key))
        # this should fail with an error since every experiment must have at
        # least one user owner
        self.assertEqual(response.content,
                         'All experiments must have at least one user as '
                         'owner. Add an additional owner first before '
                         'removing this one.')

        self.client1.logout()
        self.client3.logout()

    def testWriteAccess(self):
        # without logging in the request should be redirected
        response = self.client1.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 302)

        # now check access for user1
        login = self.client1.login(username=self.user1.username,
                                   password='******')
        self.assertTrue(login)
        response = self.client1.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # write access has not been granted for experiment2
        response = self.client1.get('/experiment/edit/%i/' % (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # neither experiment3 which is public
        response = self.client1.get('/experiment/edit/%i/' % (self.experiment3.id))
        self.assertEqual(response.status_code, 403)

        # create a group 'group1w' with write permissions
        response = self.client1.get('/experiment/control_panel'
                                    '/create/group/?group=%s&authMethod=localdb'
                                    % ('group1w'))
        self.assertEqual(response.status_code, 200)

        response = self.client1.get('/experiment/control_panel/%i'
                                    '/access_list/add/group/%s/?canRead=true'
                                    '&canWrite=true&canDelete=false&isOwner=undefined'
                                    % (self.experiment1.id, 'group1w'))
        self.assertEqual(response.status_code, 200)

        # add user2 to 'group1w' which gives him write permissions
        group = Group.objects.get(name='group1w')
        response = self.client1.get('/group/%i/add/%s/?isAdmin=false&authMethod=%s'
                                   % (group.id, self.user2.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # add user3 explicitly to experiment1
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s&canRead=true'
                                    '&canWrite=true'
                                    % (self.experiment1.id,
                                       self.user3.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # check newly created permissions for user2 and user3
        response = self.client2.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 302)

        response = self.client3.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 302)

        login = self.client2.login(username=self.user2.username, password='******')
        self.assertTrue(login)

        login = self.client3.login(username=self.user3.username, password='******')
        self.assertTrue(login)

        # response = self.client2.get('/experiment/edit/%i/' % (self.experiment1.id))
        # self.assertEqual(response.status_code, 200)

        response = self.client3.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # now the fancy stuff with timestamps
        today = datetime.datetime.today()
        yesterday = today - datetime.timedelta(days=1)
        tomorrow = today + datetime.timedelta(days=1)

        url = '/experiment/control_panel/%i/access_list/change/group/%i/'

        # give group 'group1w' write permissions for experiment1 effictive TOMORROW
        response = self.client1.post(url % (self.experiment1.id, group.id),
                                     {'canRead': True,
                                      'canWrite': True,
                                      'effectiveDate_year': tomorrow.year,
                                      'effectiveDate_month': tomorrow.month,
                                      'effectiveDate_day': tomorrow.day,
                                      })

        self.assertEqual(response.status_code, 302)

        response = self.client2.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # change effictive date to TODAY
        response = self.client1.post(url % (self.experiment1.id, group.id),
                          {'canRead': True,
                           'canWrite': True,
                           'effectiveDate_year': today.year,
                           'effectiveDate_month': today.month,
                           'effectiveDate_day': today.day,
                           })
        self.assertEqual(response.status_code, 302)

        # now user2 should have write access again
        response = self.client2.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # repeat all the tests with timestamps for user3
        url = '/experiment/control_panel/%i/access_list/change/user/%s/'

        # give user3 write permissions for experiment1 effictive TOMORROW
        response = self.client1.post(url % (self.experiment1.id, self.user3.username),
                                     {'canRead': True,
                                      'canWrite': True,
                                      'effectiveDate_year': tomorrow.year,
                                      'effectiveDate_month': tomorrow.month,
                                      'effectiveDate_day': tomorrow.day,
                                      })
        self.assertEqual(response.status_code, 302)

        response = self.client3.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # change effictive date to TODAY
        response = self.client1.post(url % (self.experiment1.id, self.user3.username),
                                     {'canRead': True,
                                      'canWrite': True,
                                      'effectiveDate_year': today.year,
                                      'effectiveDate_month': today.month,
                                      'effectiveDate_day': today.day,
                                      })
        self.assertEqual(response.status_code, 302)

        # now user3 should have write access again
        response = self.client3.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        self.client1.logout()
        self.client2.logout()
        self.client3.logout()

    def testCantEditLockedExperiment(self):
        login = self.client3.login(username=self.user3.username, password='******')
        self.assertTrue(login)

        # user3 has acl to write to experiment3
        acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user3.id),
            content_object=self.experiment3,
            canRead=True,
            canWrite=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
        )
        acl.save()

        response = self.client3.get('/experiment/edit/%i/' % (self.experiment3.id))
        self.assertEqual(response.status_code, 403)

        response = self.client3.post('/experiment/edit/%i/' % (self.experiment3.id),
                                     {'anything': True, })
        self.assertEqual(response.status_code, 403)

        acl.delete()
        self.client3.logout()

    def testOwnedExperiments(self):
        user = AnonymousUser()
        # not logged in
        class MockRequest:
            pass
        request = MockRequest()
        request.user = user
        num_exps = Experiment.safe.owned(request.user).count()
        self.assertEqual(num_exps, 0)

    def testCantAddTokenuserToGroups(self):
        from django.conf import settings
        login = self.client3.login(username=self.user3.username, password='******')
        self.assertTrue(login)
        g = Group()
        g.save()
        self.client3.get('/group/%s/%s/' % (g.id, settings.TOKEN_USERNAME))
        self.assertEqual(0, g.user_set.count())  # user should not be added
class ExperimentACLTestCase(TestCase):
    urls = 'tardis.urls'

    def setUp(self):

        # create a couple of test users
        self.user1 = User.objects.create_user('testuser1', '', 'secret')
        self.user2 = User.objects.create_user('testuser2', '', 'secret')
        self.user3 = User.objects.create_user('testuser3', '', 'secret')
        self.user4 = User.objects.create_user('testuser4', '', 'secret')

        # each user will have their own client
        self.client1 = Client()
        self.client2 = Client()
        self.client3 = Client()
        self.client4 = Client()

        # user1 will own experiment1
        self.experiment1 = Experiment(
            title='Experiment1',
            institution_name='Australian Synchrotron',
            approved=True,
            public=False,
            created_by=self.user1,
            )
        self.experiment1.save()

        # user2 will own experiment2
        self.experiment2 = Experiment(
            title='Experiment2',
            institution_name='Australian Synchrotron',
            approved=True,
            public=False,
            created_by=self.user2,
            )
        self.experiment2.save()

        # experiment3 is public
        self.experiment3 = Experiment(
            title='Experiment3',
            institution_name='Australian Synchrotron',
            approved=True,
            public=True,
            created_by=self.user3,
            )
        self.experiment3.save()

        # experiment4 will be accessible based on location information
        self.experiment4 = Experiment(
            title='Experiment4',
            institution_name='Australian Synchrotron',
            approved=True,
            public=False,
            created_by=self.user1,
            )
        self.experiment4.save()

        # user1 owns experiment1
        acl = ExperimentACL(
            pluginId=django_user,
            entityId=str(self.user1.id),
            experiment=self.experiment1,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ExperimentACL.OWNER_OWNED,
            )
        acl.save()

        # user2 owns experiment2
        acl = ExperimentACL(
            pluginId=django_user,
            entityId=str(self.user2.id),
            experiment=self.experiment2,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ExperimentACL.OWNER_OWNED,
            )
        acl.save()

        # experiment4 is accessible via location
        acl = ExperimentACL(
            pluginId='ip_address',
            entityId='127.0.0.1',
            experiment=self.experiment4,
            canRead=True,
            aclOwnershipType=ExperimentACL.SYSTEM_OWNED,
            )
        acl.save()

    def tearDown(self):
        self.client1.logout()
        self.client2.logout()
        self.client3.logout()
        self.client4.logout()

        self.experiment1.delete()
        self.experiment2.delete()
        self.experiment3.delete()
        self.experiment4.delete()

        self.user1.delete()
        self.user2.delete()
        self.user3.delete()
        self.user4.delete()

    def testAccessControl(self):
        login = self.client1.login(username='******', password='******')
        self.assertTrue(login)

        # user1 should be see experiment1
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user1 should not be allowed to see experiment2
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # user1 should be allowed to see experiment3 as it's public
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user1 should be allowed to see experiment4 based on his IP address
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment4.id))
        self.assertEqual(response.status_code, 200)

        # create a group and add it to experiment1
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/group/%s?canRead=true&create=true'
                                   % (self.experiment1.id, 'group1'))
        self.assertEqual(response.status_code, 200)

        # add user2 as admin to the newly created group
        group = Group.objects.get(name='group1')
        response = self.client1.get('/group/%i/add/%s?isAdmin=true'
                                   % (group.id, self.user2.username))
        self.assertEqual(response.status_code, 200)

        self.client1.logout()

        # now check user2's permissions
        login = self.client2.login(username='******', password='******')
        self.assertTrue(login)

        # user2 should be able to see experiment1 now
        response = self.client2.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be also able to see experiment2
        response = self.client2.get('/experiment/view/%i/'
                                   % (self.experiment2.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be allowed to see experiment3 as it's public
        response = self.client2.get('/experiment/view/%i/'
                                   % (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be able to add user3 to group1 (experiment1)
        response = self.client2.get('/group/%i/add/%s?isAdmin=false'
                                   % (group.id, self.user3.username))

        self.client1.logout()

        # now check user3's permissions
        login = self.client3.login(username='******', password='******')
        self.assertTrue(login)

        # user3 should be able to see experiment1 via his group permissions
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user3 should not be able to see experiment2
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # user3 should be able to see experiment3
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user3 should not be able to add another user4 to group1
        response = self.client3.get('/group/%i/add/%s?isAdmin=false'
                                   % (group.id, self.user4.username))
        self.assertEqual(response.status_code, 403)

        self.client3.logout()

        # ok, now do some tricky stuff
        import datetime
        today = datetime.datetime.today()
        yesterday = today - datetime.timedelta(days=1)
        tomorrow = today + datetime.timedelta(days=1)

        url = '/experiment/control_panel/%i/access_list/change/user/%s/'

        login = self.client1.login(username='******', password='******')
        self.assertTrue(login)

        # remove user3 from group1
        response = self.client1.get('/group/%i/remove/%s/'
                                   % (group.id, self.user3.username))
        self.assertEqual(response.status_code, 200)

        # add user3 to experiment1
        self.client1.get('/experiment/control_panel/%i/access_list/add/user/%s'
                         % (self.experiment1.id, self.user3.username))
        self.assertEqual(response.status_code, 200)

        # give user3 read permissions for experiment1 effictive TOMORROW
        self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'effectiveDate_year': tomorrow.year,
                           'effectiveDate_month': tomorrow.month,
                           'effectiveDate_day': tomorrow.day,
                           })
        self.assertEqual(response.status_code, 200)

        # check permissions for user3
        login = self.client3.login(username='******', password='******')
        self.assertTrue(login)

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # change effictive date to TODAY
        self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'effectiveDate_year': today.year,
                           'effectiveDate_year': today.month,
                           'effectiveDate_year': today.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # change effictive date to YESTERDAY
        self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'effectiveDate_year': yesterday.year,
                           'effectiveDate_year': yesterday.month,
                           'effectiveDate_year': yesterday.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to TOMORROW
        self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'expiryDate_year': tomorrow.year,
                           'expiryDate_month': tomorrow.month,
                           'expiryDate_day': tomorrow.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to TODAY
        self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'expiryDate_year': today.year,
                           'expiryDate_month': today.month,
                           'expiryDate_day': today.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to YESTERDAY
        self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'expiryDate_year': yesterday.year,
                           'expiryDate_month': yesterday.month,
                           'expiryDate_day': yesterday.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # can't think of any more stuff atm...
        self.client1.logout()
        self.client3.logout()
예제 #11
0
class DownloadTestCase(TestCase):

    def setUp(self):
        # create a test user
        self.user = User.objects.create_user(username='******',
                                             email='',
                                             password='******')

        # create a public experiment
        self.experiment1 = Experiment(title='Experiment 1',
                                      created_by=self.user,
                                      public_access=Experiment.PUBLIC_ACCESS_FULL)
        self.experiment1.save()

        # create a non-public experiment
        self.experiment2 = Experiment(title='Experiment 2',
                                      created_by=self.user,
                                      public_access=Experiment.PUBLIC_ACCESS_NONE)
        self.experiment2.save()

        # dataset1 belongs to experiment1
        self.dataset1 = Dataset(experiment=self.experiment1)
        self.dataset1.save()

        # dataset2 belongs to experiment2
        self.dataset2 = Dataset(experiment=self.experiment2)
        self.dataset2.save()

        # absolute path first
        filename1 = 'testfile.txt'
        filename2 = 'testfile.tiff'
        self.dest1 = abspath(join(settings.FILE_STORE_PATH, '%s/%s/'
                                  % (self.experiment1.id,
                                  self.dataset1.id)))
        self.dest2 = abspath(join(settings.FILE_STORE_PATH,
                                '%s/%s/'
                                  % (self.experiment2.id,
                                  self.dataset2.id)))
        if not exists(self.dest1):
            makedirs(self.dest1)
        if not exists(self.dest2):
            makedirs(self.dest2)

        testfile1 = abspath(join(self.dest1, filename1))
        f = open(testfile1, 'w')
        f.write("Hello World!\n")
        f.close()

        testfile2 = abspath(join(self.dest2, filename2))
        if IMAGEMAGICK_AVAILABLE:
            with Image(filename='logo:') as img:
                img.format = 'tiff'
                img.save(filename=testfile2)
        else:
            # Apparently ImageMagick isn't installed...
            # Write a "fake" TIFF file
            f = open(testfile2, 'w')
            f.write("II\x2a\x00")
            f.close()


        self.dataset_file1 = Dataset_File(dataset=self.dataset1,
                                          filename=filename1,
                                          protocol='tardis',
                                          url='tardis://%s' % filename1)
        self.dataset_file1.save()

        self.dataset_file2 = Dataset_File(dataset=self.dataset2,
                                          filename=basename(filename2),
                                          protocol='tardis',
                                          url='tardis://%s' % filename2)
        self.dataset_file2.save()

    def tearDown(self):
        self.user.delete()
        self.experiment1.delete()
        self.experiment2.delete()
        rmtree(self.dest1)
        rmtree(self.dest2)

    def testView(self):
        client = Client()

        # check view of file1
        response = client.get('/datafile/view/%i/' % self.dataset_file1.id)

        self.assertEqual(response['Content-Disposition'],
                         'inline; filename="%s"'
                         % self.dataset_file1.filename)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Hello World!\n')

        # check view of file2
        response = client.get('/datafile/view/%i/' % self.dataset_file2.id)
        # Should be forbidden
        self.assertEqual(response.status_code, 403)

        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        # check view of file2 again
        response = client.get('/datafile/view/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 200)

        # The following behaviour relies on ImageMagick
        if IMAGEMAGICK_AVAILABLE:
            # file2 should have a ".png" filename
            self.assertEqual(response['Content-Disposition'],
                             'inline; filename="%s"'
                             % (self.dataset_file2.filename+'.png'))
            # file2 should be a PNG
            self.assertEqual(response['Content-Type'], 'image/png')
            png_signature = "\x89PNG\r\n\x1a\n"
            self.assertEqual(response.content[0:8], png_signature)
        else:
            # file2 should have a ".tiff" filename
            self.assertEqual(response['Content-Disposition'],
                             'inline; filename="%s"'
                             % (self.dataset_file2.filename))
            # file2 should be a TIFF
            self.assertEqual(response['Content-Type'], 'image/tiff')
            tiff_signature = "II\x2a\x00"
            self.assertEqual(response.content[0:4], tiff_signature)


    def testDownload(self):
        client = Client()

        # check download for experiment1
        response = client.get('/download/experiment/%i/zip/' % self.experiment1.id)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="experiment%s-complete.zip"'
                         % self.experiment1.id)
        self.assertEqual(response.status_code, 200)

        # check download of file1
        response = client.get('/download/datafile/%i/' % self.dataset_file1.id)

        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s"'
                         % self.dataset_file1.filename)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Hello World!\n')

        # requesting file2 should be forbidden...
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 403)

        # check dataset1 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [self.dataset1.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 200)

        # check dataset2 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [self.dataset2.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 403)

        # check datafile1 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [],
                                'datafile': [self.dataset_file1.id]})
        self.assertEqual(response.status_code, 200)
        # It should be a zip file (all of which start with "PK")
        self.assertEqual(response.content[0:2], "PK")

        # check datafile2 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [],
                                'datafile': [self.dataset_file2.id]})
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to "metadata only"
        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_METADATA
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        # Metadata-only means "no file access"!
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to public
        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 200)
        # This should be a TIFF (which often starts with "II\x2a\x00")
        self.assertEqual(response['Content-Type'], 'image/tiff')
        self.assertEqual(response.content[0:4], "II\x2a\x00")


    def testDatasetFile(self):

        # check registered text file for physical file meta information
        df = Dataset_File.objects.get(pk=self.dataset_file1.id)

        try:
            from magic import Magic
            self.assertEqual(df.mimetype, 'text/plain; charset=us-ascii')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(df.size, str(13))
        self.assertEqual(df.md5sum, '8ddd8be4b179a529afa5f2ffae4b9858')

        # now check a JPG file
        filename = join(abspath(dirname(__file__)),
                        '../static/images/ands-logo-hi-res.jpg')

        dataset = Dataset.objects.get(pk=self.dataset1.id)

        pdf1 = Dataset_File(dataset=dataset,
                            filename=basename(filename),
                            url='file://%s' % filename,
                            protocol='file')
        pdf1.save()
        try:
            from magic import Magic
            self.assertEqual(pdf1.mimetype, 'image/jpeg')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(pdf1.size, str(14232))
        self.assertEqual(pdf1.md5sum, 'c450d5126ffe3d14643815204daf1bfb')

        # now check that we can override the physical file meta information
        pdf2 = Dataset_File(dataset=dataset,
                            filename=basename(filename),
                            url='file://%s' % filename,
                            protocol='file',
                            mimetype='application/vnd.openxmlformats-officedocument.presentationml.presentation',
                            size=str(0),
                            md5sum='md5sum')
        pdf2.save()
        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(pdf2.size, str(0))
        self.assertEqual(pdf2.md5sum, 'md5sum')

        pdf2.mimetype = ''
        pdf2.save()

        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/pdf')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
예제 #12
0
class ViewTemplateContextsTest(TestCase):
    def setUp(self):
        """
        setting up essential objects, copied from tests above
        """

        user = "******"
        pwd = "secret"
        email = ""
        self.user = User.objects.create_user(user, email, pwd)
        self.userProfile = self.user.userprofile
        self.exp = Experiment(title="test exp1", institution_name="monash", created_by=self.user)
        self.exp.save()
        self.acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user.id),
            content_object=self.exp,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
        )
        self.acl.save()
        self.dataset = Dataset(description="dataset description...")
        self.dataset.save()
        self.dataset.experiments.add(self.exp)
        self.dataset.save()

        self.datafile = DataFile(dataset=self.dataset, size=42, filename="foo", md5sum="junk")
        self.datafile.save()

    def tearDown(self):
        self.user.delete()
        self.exp.delete()
        self.dataset.delete()
        self.datafile.delete()
        self.acl.delete()

    def testExperimentView(self):
        """
        test some template context parameters for an experiment view
        """
        from tardis.tardis_portal.views import ExperimentView
        from django.http import HttpRequest
        import sys

        # Default behavior
        views_module = flexmock(sys.modules["tardis.tardis_portal.views"])
        request = HttpRequest()
        request.method = "GET"
        request.user = self.user
        request.groups = []
        context = {
            "organization": ["test", "test2"],
            "default_organization": "test",
            "default_format": "tar",
            "protocol": [["tgz", "/download/experiment/1/tgz/"], ["tar", "/download/experiment/1/tar/"]],
        }
        views_module.should_call("render_response_index").with_args(
            _AnyMatcher(), "tardis_portal/view_experiment.html", _ContextMatcher(context)
        )
        view_fn = ExperimentView.as_view()
        response = view_fn(request, experiment_id=self.exp.id)
        self.assertEqual(response.status_code, 200)

        # Behavior with USER_AGENT_SENSING enabled and a request.user_agent
        saved_setting = getattr(settings, "USER_AGENT_SENSING", None)
        try:
            setattr(settings, "USER_AGENT_SENSING", True)
            request = HttpRequest()
            request.method = "GET"
            request.user = self.user
            request.groups = []
            mock_agent = _MiniMock(os=_MiniMock(family="Macintosh"))
            setattr(request, "user_agent", mock_agent)
            context = {
                "organization": ["classic", "test", "test2"],
                "default_organization": "classic",
                "default_format": "tar",
                "protocol": [["tar", "/download/experiment/1/tar/"]],
            }
            views_module.should_call("render_response_index").with_args(
                _AnyMatcher(), "tardis_portal/view_experiment.html", _ContextMatcher(context)
            )
            view_fn = ExperimentView.as_view()
            response = view_fn(request, experiment_id=self.exp.id)
            self.assertEqual(response.status_code, 200)
        finally:
            if saved_setting is not None:
                setattr(settings, "USER_AGENT_SENSING", saved_setting)
            else:
                delattr(settings, "USER_AGENT_SENSING")

    def testDatasetView(self):
        """
        test some context parameters for a dataset view
        """
        from tardis.tardis_portal.views import DatasetView
        from django.http import HttpRequest
        import sys

        views_module = flexmock(sys.modules["tardis.tardis_portal.views"])
        request = HttpRequest()
        request.method = "GET"
        request.user = self.user
        request.groups = []
        context = {"default_organization": "test", "default_format": "tar"}
        views_module.should_call("render_response_index").with_args(
            _AnyMatcher(), "tardis_portal/view_dataset.html", _ContextMatcher(context)
        )
        view_fn = DatasetView.as_view()
        response = view_fn(request, dataset_id=self.dataset.id)
        self.assertEqual(response.status_code, 200)

        # Behavior with USER_AGENT_SENSING enabled and a request.user_agent
        saved_setting = getattr(settings, "USER_AGENT_SENSING", None)
        try:
            setattr(settings, "USER_AGENT_SENSING", True)
            request = HttpRequest()
            request.method = "GET"
            request.user = self.user
            request.groups = []
            mock_agent = _MiniMock(os=_MiniMock(family="Macintosh"))
            setattr(request, "user_agent", mock_agent)
            context = {"default_organization": "classic", "default_format": "tar"}
            views_module.should_call("render_response_index").with_args(
                _AnyMatcher(), "tardis_portal/view_dataset.html", _ContextMatcher(context)
            )
            view_fn = DatasetView.as_view()
            response = view_fn(request, dataset_id=self.dataset.id)
            self.assertEqual(response.status_code, 200)
        finally:
            if saved_setting is not None:
                setattr(settings, "USER_AGENT_SENSING", saved_setting)
            else:
                delattr(settings, "USER_AGENT_SENSING")
예제 #13
0
class UploadTestCase(TestCase):
    def setUp(self):
        from os import path, mkdir
        from tempfile import mkdtemp

        user = "******"
        pwd = "secret"
        email = ""
        self.user = User.objects.create_user(user, email, pwd)

        self.userProfile = self.user.userprofile

        self.test_dir = mkdtemp()

        self.exp = Experiment(title="test exp1", institution_name="monash", created_by=self.user)
        self.exp.save()

        acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user.id),
            content_object=self.exp,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
        )
        acl.save()

        self.dataset = Dataset(description="dataset description...")
        self.dataset.save()
        self.dataset.experiments.add(self.exp)
        self.dataset.save()

        path_parts = [
            settings.FILE_STORE_PATH,
            "%s-%s" % (quote(self.dataset.description, safe="") or "untitled", self.dataset.id),
        ]
        self.dataset_path = path.join(*path_parts)

        if not path.exists(self.dataset_path):
            mkdir(self.dataset_path)

        # write test file

        self.filename = "testfile.txt"

        self.f1 = open(path.join(self.test_dir, self.filename), "w")
        self.f1.write("Test file 1")
        self.f1.close()

        self.f1_size = path.getsize(path.join(self.test_dir, self.filename))

        self.f1 = open(path.join(self.test_dir, self.filename), "r")

    def tearDown(self):
        from shutil import rmtree

        self.f1.close()
        rmtree(self.test_dir)
        rmtree(self.dataset_path)
        self.exp.delete()

    def testFileUpload(self):
        from os import path

        c = Client()
        c.login(username="******", password="******")
        session_id = c.session.session_key

        c.post("/upload/" + str(self.dataset.id) + "/", {"Filedata": self.f1, "session_id": session_id})

        test_files_db = DataFile.objects.filter(dataset__id=self.dataset.id)
        self.assertTrue(path.exists(path.join(self.dataset_path, self.filename)))
        target_id = Dataset.objects.first().id
        self.assertEqual(self.dataset.id, target_id)
        url = test_files_db[0].file_objects.all()[0].uri
        self.assertEqual(url, path.relpath("%s/testfile.txt" % self.dataset_path, settings.FILE_STORE_PATH))
        self.assertTrue(test_files_db[0].file_objects.all()[0].verified)

    def testUploadComplete(self):
        from django.http import QueryDict, HttpRequest
        from tardis.tardis_portal.views import upload_complete

        data = [("filesUploaded", "1"), ("speed", "really fast!"), ("allBytesLoaded", "2"), ("errorCount", "0")]
        post = QueryDict("&".join(["%s=%s" % (k, v) for (k, v) in data]))
        request = HttpRequest()
        request.POST = post
        response = upload_complete(request)
        self.assertTrue("<p>Number: 1</p>" in response.content)
        self.assertTrue("<p>Errors: 0</p>" in response.content)
        self.assertTrue("<p>Bytes: 2</p>" in response.content)
        self.assertTrue("<p>Speed: really fast!</p>" in response.content)
예제 #14
0
class UploadTestCase(TestCase):
    def setUp(self):
        from os import path, mkdir
        from tempfile import mkdtemp

        user = '******'
        pwd = 'secret'
        email = ''
        self.user = User.objects.create_user(user, email, pwd)

        self.userProfile = UserProfile(user=self.user)

        self.test_dir = mkdtemp()

        self.exp = Experiment(title='test exp1',
                              institution_name='monash',
                              created_by=self.user)
        self.exp.save()

        acl = ExperimentACL(
            pluginId=django_user,
            entityId=str(self.user.id),
            experiment=self.exp,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ExperimentACL.OWNER_OWNED,
        )
        acl.save()

        self.dataset = \
            Dataset(description='dataset description...')
        self.dataset.save()
        self.dataset.experiments.add(self.exp)
        self.dataset.save()

        self.experiment_path = path.join(
            settings.FILE_STORE_PATH,
            str(self.dataset.get_first_experiment().id))

        self.dataset_path = path.join(self.experiment_path,
                                      str(self.dataset.id))

        if not path.exists(self.experiment_path):
            mkdir(self.experiment_path)
        if not path.exists(self.dataset_path):
            mkdir(self.dataset_path)

        # write test file

        self.filename = 'testfile.txt'

        self.f1 = open(path.join(self.test_dir, self.filename), 'w')
        self.f1.write('Test file 1')
        self.f1.close()

        self.f1_size = path.getsize(path.join(self.test_dir, self.filename))

        self.f1 = open(path.join(self.test_dir, self.filename), 'r')

    def tearDown(self):
        from shutil import rmtree

        self.f1.close()
        rmtree(self.test_dir)
        rmtree(self.dataset_path)
        rmtree(self.experiment_path)
        self.exp.delete()

    def testFileUpload(self):
        from os import path

        c = Client()
        c.login(username='******', password='******')
        session_id = c.session.session_key

        response = c.post('/upload/' + str(self.dataset.id) + '/', {
            'Filedata': self.f1,
            'session_id': session_id
        })

        test_files_db = \
            Dataset_File.objects.filter(dataset__id=self.dataset.id)

        self.assertTrue(
            path.exists(path.join(self.dataset_path, self.filename)))
        self.assertTrue(self.dataset.id == 1)
        self.assertTrue(
            test_files_db[0].url == '%d/%d/testfile.txt' %
            (self.dataset.get_first_experiment().id, self.dataset.id))
        self.assertTrue(test_files_db[0].verified)

    def testUploadComplete(self):
        from django.http import QueryDict, HttpRequest
        from tardis.tardis_portal.views import upload_complete
        data = [('filesUploaded', '1'), ('speed', 'really fast!'),
                ('allBytesLoaded', '2'), ('errorCount', '0')]
        post = QueryDict('&'.join(['%s=%s' % (k, v) for (k, v) in data]))
        request = HttpRequest()
        request.POST = post
        response = upload_complete(request)
        self.assertTrue('<p>Number: 1</p>' in response.content)
        self.assertTrue('<p>Errors: 0</p>' in response.content)
        self.assertTrue('<p>Bytes: 2</p>' in response.content)
        self.assertTrue('<p>Speed: really fast!</p>' in response.content)
예제 #15
0
class DownloadTestCase(TestCase):
    def setUp(self):
        # create a test user
        self.user = User.objects.create_user(username='******',
                                             email='',
                                             password='******')

        Location.force_initialize()

        # create a public experiment
        self.experiment1 = Experiment(
            title='Experiment 1',
            created_by=self.user,
            public_access=Experiment.PUBLIC_ACCESS_FULL)
        self.experiment1.save()

        # create a non-public experiment
        self.experiment2 = Experiment(
            title='Experiment 2',
            created_by=self.user,
            public_access=Experiment.PUBLIC_ACCESS_NONE)
        self.experiment2.save()

        # dataset1 belongs to experiment1
        self.dataset1 = Dataset()
        self.dataset1.save()
        self.dataset1.experiments.add(self.experiment1)
        self.dataset1.save()

        # dataset2 belongs to experiment2
        self.dataset2 = Dataset()
        self.dataset2.save()
        self.dataset2.experiments.add(self.experiment2)
        self.dataset2.save()

        # absolute path first
        filename1 = 'testfile.txt'
        filename2 = 'testfile.tiff'
        self.dest1 = abspath(
            join(settings.FILE_STORE_PATH,
                 '%s/%s/' % (self.experiment1.id, self.dataset1.id)))
        self.dest2 = abspath(
            join(settings.FILE_STORE_PATH,
                 '%s/%s/' % (self.experiment2.id, self.dataset2.id)))
        if not exists(self.dest1):
            makedirs(self.dest1)
        if not exists(self.dest2):
            makedirs(self.dest2)

        testfile1 = abspath(join(self.dest1, filename1))
        f = open(testfile1, 'w')
        f.write("Hello World!\n")
        f.close()

        testfile2 = abspath(join(self.dest2, filename2))
        _generate_test_image(testfile2)

        self.datafile1 = self._build_datafile( \
            testfile1, filename1, self.dataset1,
            '%d/%d/%s' % (self.experiment1.id, self.dataset1.id, filename1))

        self.datafile2 = self._build_datafile( \
            testfile2, filename2, self.dataset2,
            '%d/%d/%s' % (self.experiment2.id, self.dataset2.id, filename2))

    def _build_datafile(self,
                        testfile,
                        filename,
                        dataset,
                        url,
                        protocol='',
                        checksum=None,
                        size=None,
                        mimetype=''):
        filesize, sha512sum = get_size_and_sha512sum(testfile)
        datafile = Dataset_File(
            dataset=dataset,
            filename=filename,
            mimetype=mimetype,
            size=str(size if size != None else filesize),
            sha512sum=(checksum if checksum else sha512sum))
        datafile.save()
        if urlparse.urlparse(url).scheme == '':
            location = Location.get_location('local')
        else:
            location = Location.get_location_for_url(url)
            if not location:
                location = Location.load_location({
                    'name':
                    filename,
                    'url':
                    urlparse.urljoin(url, '.'),
                    'type':
                    'external',
                    'priority':
                    10,
                    'transfer_provider':
                    'local'
                })
        replica = Replica(datafile=datafile,
                          protocol=protocol,
                          url=url,
                          location=location)
        replica.verify()
        replica.save()
        return Dataset_File.objects.get(pk=datafile.pk)

    def tearDown(self):
        self.user.delete()
        self.experiment1.delete()
        self.experiment2.delete()
        rmtree(self.dest1)
        rmtree(self.dest2)

    def testView(self):
        client = Client()

        # check view of file1
        response = client.get('/datafile/view/%i/' % self.datafile1.id)

        self.assertEqual(response['Content-Disposition'],
                         'inline; filename="%s"' % self.datafile1.filename)
        self.assertEqual(response.status_code, 200)
        response_content = ""
        for c in response.streaming_content:
            response_content += c
        self.assertEqual(response_content, 'Hello World!\n')

        # check view of file2
        response = client.get('/datafile/view/%i/' % self.datafile2.id)
        # Should be forbidden
        self.assertEqual(response.status_code, 403)

        self.experiment2.public_access = Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        # check view of file2 again
        response = client.get('/datafile/view/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 200)

        # The following behaviour relies on ImageMagick
        if IMAGEMAGICK_AVAILABLE:
            # file2 should have a ".png" filename
            self.assertEqual(
                response['Content-Disposition'],
                'inline; filename="%s"' % (self.datafile2.filename + '.png'))
            # file2 should be a PNG
            self.assertEqual(response['Content-Type'], 'image/png')
            png_signature = "\x89PNG\r\n\x1a\n"
            self.assertEqual(response.content[0:8], png_signature)
        else:
            # file2 should have a ".tiff" filename
            self.assertEqual(
                response['Content-Disposition'],
                'inline; filename="%s"' % (self.datafile2.filename))
            # file2 should be a TIFF
            self.assertEqual(response['Content-Type'], 'image/tiff')
            tiff_signature = "II\x2a\x00"
            self.assertEqual(response.content[0:4], tiff_signature)

    def _check_tar_file(self,
                        content,
                        rootdir,
                        datafiles,
                        simpleNames=False,
                        noTxt=False):
        with NamedTemporaryFile('w') as tempfile:
            for c in content:
                tempfile.write(c)
            tempfile.flush()
            if getsize(tempfile.name) > 0:
                expect(is_tarfile(tempfile.name)).to_be_truthy()
                try:
                    tf = TarFile(tempfile.name, 'r')
                    self._check_names(datafiles, tf.getnames(), rootdir,
                                      simpleNames, noTxt)
                finally:
                    tf.close()
            else:
                self._check_names(datafiles, [], rootdir, simpleNames, noTxt)

    def _check_zip_file(self,
                        content,
                        rootdir,
                        datafiles,
                        simpleNames=False,
                        noTxt=False):
        with NamedTemporaryFile('w') as tempfile:
            #import rpdb2; rpdb2.start_embedded_debugger("a")
            #import ipdb; ipdb.set_trace()
            for c in content:
                tempfile.write(c)
            tempfile.flush()
            # It should be a zip file
            expect(is_zipfile(tempfile.name)).to_be_truthy()
            try:
                zf = ZipFile(tempfile.name, 'r')
                self._check_names(datafiles, zf.namelist(), rootdir,
                                  simpleNames, noTxt)
            finally:
                zf.close()

    def _check_names(self, datafiles, names, rootdir, simpleNames, noTxt):
        # SimpleNames says if we expect basenames or pathnames
        # NoTxt says if we expect '.txt' files to be filtered out
        if not noTxt:
            expect(len(names)).to_equal(len(datafiles))
        for df in datafiles:
            if simpleNames:
                filename = df.filename
            else:
                filename = join(df.filename)  # TODO: update 'classic' to a
                # useful method and adapt test
            expect(filename in names).to_be(not (
                noTxt and filename.endswith('.txt')))

    def testDownload(self):
        client = Client()

        # check download for experiment1
        # disable zip test while zip is disabled
        # response = client.get('/download/experiment/%i/zip/' % \
        #                           self.experiment1.id)
        # self.assertEqual(response['Content-Disposition'],
        #                  'attachment; filename="experiment%s-complete.zip"'
        #                  % self.experiment1.id)
        # self.assertEqual(response.status_code, 200)
        # self._check_zip_file(
        #     response.streaming_content, str(self.experiment1.id),
        #     reduce(lambda x, y: x + y,
        #            [ds.dataset_file_set.all() \
        #                 for ds in self.experiment1.datasets.all()]))

        # check download for experiment1 as tar
        response = client.get('/download/experiment/%i/tar/test/' %
                              self.experiment1.id)
        self.assertEqual(
            response['Content-Disposition'],
            'attachment; filename="%s-complete.tar"' %
            self.experiment1.title.replace(' ', '_'))
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(
            response.streaming_content,
            str(self.experiment1.title.replace(' ', '_')),
            reduce(lambda x, y: x + y, [
                ds.dataset_file_set.all()
                for ds in self.experiment1.datasets.all()
            ]))

        # check download of file1
        response = client.get('/download/datafile/%i/' % self.datafile1.id)

        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s"' % self.datafile1.filename)
        self.assertEqual(response.status_code, 200)
        response_content = ""
        for c in response.streaming_content:
            response_content += c
        self.assertEqual(response_content, 'Hello World!\n')

        # requesting file2 should be forbidden...
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 403)

        # check dataset1 download
        # zips disabled for now
        # response = client.post('/download/datafiles/',
        #                        {'expid': self.experiment1.id,
        #                         'dataset': [self.dataset1.id],
        #                         'datafile': []})
        # self.assertEqual(response.status_code, 200)
        # self._check_zip_file(response.streaming_content, 'datasets',
        #                      self.dataset1.dataset_file_set.all())

        # check dataset1 download as tar
        response = client.post(
            '/download/datafiles/', {
                'expid': self.experiment1.id,
                'dataset': [self.dataset1.id],
                'datafile': [],
                'comptype': 'tar'
            })
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(response.streaming_content,
                             'Experiment 1-selection',
                             self.dataset1.dataset_file_set.all())

        # check dataset2 download
        response = client.post(
            '/download/datafiles/', {
                'expid': self.experiment2.id,
                'dataset': [self.dataset2.id],
                'datafile': []
            })
        self.assertEqual(response.status_code, 403)

        # check datafile1 download via POST
        response = client.post(
            '/download/datafiles/', {
                'expid': self.experiment1.id,
                'dataset': [],
                'datafile': [self.datafile1.id]
            })
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(response.streaming_content,
                             'Experiment 1-selection', [self.datafile1])

        # check datafile2 download via POST
        response = client.post(
            '/download/datafiles/', {
                'expid': self.experiment2.id,
                'dataset': [],
                'datafile': [self.datafile2.id]
            })
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to "metadata only"
        self.experiment2.public_access = Experiment.PUBLIC_ACCESS_METADATA
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        # Metadata-only means "no file access"!
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to public
        self.experiment2.public_access = Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 200)
        # This should be a TIFF (which often starts with "II\x2a\x00")
        self.assertEqual(response['Content-Type'], 'image/tiff')
        response_content = ""
        for c in response.streaming_content:
            response_content += c
        self.assertEqual(response_content[0:4], "II\x2a\x00")

        # check experiment zip download with alternative organization
        # disable zip for now
        # response = client.get('/download/experiment/%i/zip/test/' % \
        #                           self.experiment1.id)
        # self.assertEqual(response.status_code, 200)
        # self.assertEqual(response['Content-Disposition'],
        #                  'attachment; filename="%s-complete.zip"'
        #                  % self.experiment1.title)
        # self._check_zip_file(
        #     response.streaming_content, str(self.experiment1.id),
        #     reduce(lambda x, y: x + y,
        #            [ds.dataset_file_set.all() \
        #                 for ds in self.experiment1.datasets.all()]),
        #     simpleNames=True)

        # check experiment tar download with alternative organization
        response = client.get('/download/experiment/%i/tar/test/' % \
                                  self.experiment1.id)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response['Content-Disposition'],
            'attachment; filename="%s-complete.tar"' %
            self.experiment1.title.replace(' ', '_'))
        self._check_tar_file(
            response.streaming_content, str(self.experiment1.id),
            reduce(lambda x, y: x + y,
                   [ds.dataset_file_set.all() \
                        for ds in self.experiment1.datasets.all()]),
            simpleNames=True)

        # check experiment1 download with '.txt' filtered out (none left)
        response = client.get('/download/experiment/%i/tar/test2/' % \
                                  self.experiment1.id)
        self.assertEqual(response.status_code, 200)

        # check experiment2 download with '.txt' filtered out
        response = client.get('/download/experiment/%i/tar/test2/' % \
                                  self.experiment2.id)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response['Content-Disposition'],
            'attachment; filename="%s-complete.tar"' %
            self.experiment2.title.replace(' ', '_'))
        self._check_tar_file(
            response.streaming_content, str(self.experiment2.id),
            reduce(lambda x, y: x + y,
                   [ds.dataset_file_set.all() \
                        for ds in self.experiment2.datasets.all()]),
            simpleNames=True, noTxt=True)

        # check dataset1 download
        # zips disabled for now
        # response = client.post('/download/datafiles/',
        #                        {'expid': self.experiment1.id,
        #                         'dataset': [self.dataset1.id],
        #                         'datafile': [],
        #                         'comptype': 'zip',
        #                         'organization': 'test'})
        # self.assertEqual(response.status_code, 200)
        # self._check_zip_file(response.streaming_content, 'datasets',
        #                      self.dataset1.dataset_file_set.all(),
        #                      simpleNames=True)

    def testDatasetFile(self):

        # check registered text file for physical file meta information
        df = Dataset_File.objects.get(pk=self.datafile1.id)

        try:
            from magic import Magic
            self.assertEqual(df.mimetype, 'text/plain; charset=us-ascii')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(df.size, str(13))
        self.assertEqual(df.md5sum, '8ddd8be4b179a529afa5f2ffae4b9858')

        # Now check we can calculate checksums and infer the mime type
        # for a JPG file.
        filename = abspath(
            join(dirname(__file__), '../static/images/ands-logo-hi-res.jpg'))

        dataset = Dataset.objects.get(pk=self.dataset1.id)

        pdf1 = self._build_datafile(filename,
                                    basename(filename),
                                    dataset,
                                    'file://%s' % filename,
                                    protocol='file')
        self.assertEqual(pdf1.get_preferred_replica().verify(), True)
        pdf1 = Dataset_File.objects.get(pk=pdf1.pk)

        try:
            from magic import Magic
            self.assertEqual(pdf1.mimetype, 'image/jpeg')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(pdf1.size, str(14232))
        self.assertEqual(pdf1.md5sum, 'c450d5126ffe3d14643815204daf1bfb')

        # Now check that we can override the physical file meta information
        # We are setting size/checksums that don't match the actual file, so
        # the
        pdf2 = self._build_datafile(
            filename,
            filename,
            dataset,
            'file://%s' % filename,
            protocol='file',
            mimetype=
            'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            size=0,
            # Empty string always has the same hash
            checksum=
            'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e'
        )
        self.assertEqual(pdf2.size, str(0))
        self.assertEqual(pdf2.md5sum, '')
        self.assertEqual(pdf2.get_preferred_replica().verify(), False)
        pdf2 = Dataset_File.objects.get(pk=pdf2.pk)
        try:
            from magic import Magic
            self.assertEqual(
                pdf2.mimetype,
                'application/vnd.openxmlformats-officedocument.presentationml.presentation'
            )
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(pdf2.size, str(0))
        self.assertEqual(pdf2.md5sum, '')

        pdf2.mimetype = ''
        pdf2.save()
        pdf2.get_preferred_replica().save()
        pdf2 = Dataset_File.objects.get(pk=pdf2.pk)

        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/pdf')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
예제 #16
0
class ContextualViewTest(TestCase):

    def setUp(self):
        """
        setting up essential objects, copied from tests above
        """
        user = '******'
        pwd = 'secret'
        email = ''
        self.user = User.objects.create_user(user, email, pwd)
        self.userProfile = UserProfile(user=self.user).save()
        self.exp = Experiment(title='test exp1',
                              institution_name='monash', created_by=self.user)
        self.exp.save()
        self.acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user.id),
            content_object=self.exp,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
        )
        self.acl.save()
        self.dataset = Dataset(description='dataset description...')
        self.dataset.save()
        self.dataset.experiments.add(self.exp)
        self.dataset.save()

        self.dataset_file = Dataset_File(dataset=self.dataset,
                                         size=42, filename="foo",
                                         md5sum="junk")
        self.dataset_file.save()

        self.testschema = Schema(namespace="http://test.com/test/schema",
                                 name="Test View",
                                 type=Schema.DATAFILE,
                                 hidden=True)
        self.testschema.save()
        self.dfps = DatafileParameterSet(dataset_file=self.dataset_file,
                                         schema=self.testschema)
        self.dfps.save()

    def tearDown(self):
        self.user.delete()
        self.exp.delete()
        self.dataset.delete()
        self.dataset_file.delete()
        self.testschema.delete()
        self.dfps.delete()
        self.acl.delete()

    def testDetailsDisplay(self):
        """
        test display of view for an existing schema and no display for an undefined one.
        """
        from tardis.tardis_portal.views import display_datafile_details
        request = flexmock(user=self.user, groups=[("testgroup",flexmock())])
        with self.settings(DATAFILE_VIEWS=[("http://test.com/test/schema", "/test/url"),
                                           ("http://does.not.exist", "/false/url")]):
            response = display_datafile_details(request, dataset_file_id=self.dataset_file.id)
            self.assertEqual(response.status_code, 200)
            self.assertTrue("/ajax/parameters/" in response.content)
            self.assertTrue("/test/url" in response.content)
            self.assertFalse("/false/url" in response.content)
예제 #17
0
class ObjectACLTestCase(TestCase):
    urls = 'tardis.urls'

    def setUp(self):

        # create a couple of test users
        self.user1 = User.objects.create_user('testuser1', '', 'secret')
        self.user2 = User.objects.create_user('testuser2', '', 'secret')
        self.user3 = User.objects.create_user('testuser3', '', 'secret')
        self.user4 = User.objects.create_user('testuser4', '', 'secret')

        # with standard permissions
        for user in [self.user1, self.user2, self.user3, self.user4]:
            user.user_permissions.add(
                Permission.objects.get(codename='add_experiment'))
            user.user_permissions.add(
                Permission.objects.get(codename='change_experiment'))
            user.user_permissions.add(
                Permission.objects.get(codename='change_group'))
            user.user_permissions.add(
                Permission.objects.get(codename='change_userauthentication'))
            user.user_permissions.add(
                Permission.objects.get(codename='change_objectacl'))

        self.userProfile1 = self.user1.userprofile
        self.userProfile2 = self.user2.userprofile
        self.userProfile3 = self.user3.userprofile
        self.userProfile4 = self.user4.userprofile

        # each user will have their own client
        self.client1 = Client()
        self.client2 = Client()
        self.client3 = Client()
        self.client4 = Client()

        # user1 will own experiment1
        self.experiment1 = Experiment(
            title='Experiment1',
            institution_name='Australian Synchrotron',
            approved=True,
            public_access=Experiment.PUBLIC_ACCESS_NONE,
            created_by=self.user1,
        )
        self.experiment1.save()

        # user2 will own experiment2
        self.experiment2 = Experiment(
            title='Experiment2',
            institution_name='Australian Synchrotron',
            approved=True,
            public_access=Experiment.PUBLIC_ACCESS_NONE,
            created_by=self.user2,
        )
        self.experiment2.save()

        # experiment3 is public & locked
        self.experiment3 = Experiment(
            title='Experiment3',
            institution_name='Australian Synchrotron',
            approved=True,
            locked=True,
            public_access=Experiment.PUBLIC_ACCESS_FULL,
            created_by=self.user3,
        )
        self.experiment3.save()

        # experiment4 will be accessible based on location information
        self.experiment4 = Experiment(
            title='Experiment4',
            institution_name='Australian Synchrotron',
            approved=True,
            public_access=Experiment.PUBLIC_ACCESS_NONE,
            created_by=self.user1,
        )
        self.experiment4.save()

        # user1 owns experiment1
        acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user1.id),
            content_object=self.experiment1,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
        )
        acl.save()

        # user2 owns experiment2
        acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user2.id),
            content_object=self.experiment2,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
        )
        acl.save()

        # experiment4 is accessible via location
        acl = ObjectACL(
            pluginId='ip_address',
            entityId='127.0.0.1',
            content_object=self.experiment4,
            canRead=True,
            aclOwnershipType=ObjectACL.SYSTEM_OWNED,
        )
        acl.save()

    def tearDown(self):

        self.experiment1.delete()
        self.experiment2.delete()
        self.experiment3.delete()
        self.experiment4.delete()

        self.user1.delete()
        self.user2.delete()
        self.user3.delete()
        self.user4.delete()

        self.client1.logout()
        self.client2.logout()
        self.client3.logout()
        self.client4.logout()

    def testChangeUserPermissions(self):
        login1 = self.client1.login(username=self.user1.username,
                                    password='******')
        self.assertTrue(login1)

        login3 = self.client3.login(username=self.user3.username,
                                    password='******')
        self.assertTrue(login3)

        # user1 should be see experiment1
        response = self.client1.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user3 should not be able to see experiment1
        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # make the group1 a full read/write/owner of the experiment1
        response = self.client1.get(
            '/experiment/control_panel/%i'
            '/access_list/add/group/%s/?canRead=true'
            '&canWrite=true&canDelete=false&isOwner=true' %
            (self.experiment1.id, 'group1'))
        self.assertEqual(response.status_code, 200)

        # ok, now do some tricky stuff
        today = datetime.datetime.today()
        yesterday = today - datetime.timedelta(days=1)
        tomorrow = today + datetime.timedelta(days=1)

        # add user3 to experiment1
        response = self.client1.get(
            '/experiment/control_panel/%i/access_list'
            '/add/user/%s/?authMethod=%s' %
            (self.experiment1.id, self.user3.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, '<div class="access_list_user')

        # check permissions for user3 - fail as canRead not set to True
        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # give user3 read permissions for experiment1 effective TOMORROW
        url = ("/experiment/control_panel/%i/access_list"
               "/change/user/%s/?authMethod=%s")

        response = self.client1.post(
            url % (self.experiment1.id, self.user3.username, localdb_auth_key),
            {
                'canRead': True,
                'effectiveDate_year': tomorrow.year,
                'effectiveDate_month': tomorrow.month,
                'effectiveDate_day': tomorrow.day,
            })
        self.assertEqual(response.status_code, 302)

        # check permissions for user3
        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # user1 should be see experiment1
        response = self.client1.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # give user3 read permissions for experiment1 effective YESTERDAY
        url = ("/experiment/control_panel/%i/access_list"
               "/change/user/%s/?authMethod=%s")

        response = self.client1.post(
            url % (self.experiment1.id, self.user3.username, localdb_auth_key),
            {
                'canRead': True,
                'effectiveDate_year': yesterday.year,
                'effectiveDate_month': yesterday.month,
                'effectiveDate_day': yesterday.day,
            })
        self.assertEqual(response.status_code, 302)

        # check permissions for user3
        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

    def testReadAccess(self):
        login = self.client1.login(username=self.user1.username,
                                   password='******')
        self.assertTrue(login)

        # user1 should be see experiment1
        response = self.client1.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user1 should not be allowed to see experiment2
        response = self.client1.get('/experiment/view/%i/' %
                                    (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # user1 should be allowed to see experiment3 as it's public
        response = self.client1.get('/experiment/view/%i/' %
                                    (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user1 should be allowed to see experiment4 based on his IP address
        # response = self.client1.get('/experiment/view/%i/'
        #                            % (self.experiment4.id))
        # self.assertEqual(response.status_code, 200)

        # create a group and add it to experiment1
        response = self.client1.get(
            '/experiment/control_panel'
            '/create/group/?group=%s&authMethod=localdb' % ('group1'))
        self.assertEqual(response.status_code, 200)

        # make the group1 a full read/write/owner of the experiment1
        response = self.client1.get(
            '/experiment/control_panel/%i'
            '/access_list/add/group/%s/?canRead=true'
            '&canWrite=true&canDelete=false&isOwner=true' %
            (self.experiment1.id, 'group1'))
        self.assertEqual(response.status_code, 200)

        # add user2 as admin to the newly created group1
        group = Group.objects.get(name='group1')
        response = self.client1.get(
            '/group/%i/add/%s/?isAdmin=true&authMethod=%s' %
            (group.id, self.user2.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # try it again
        response = self.client1.get(
            '/group/%i/add/%s/?isAdmin=true&authMethod=%s' %
            (group.id, self.user2.username, localdb_auth_key))
        self.assertEqual(
            response.content, 'User %s is already member of that'
            ' group.' % self.user2.username)

        # user1 is not allowed to modify acls for experiment2
        response = self.client1.get(
            '/experiment/control_panel/%i/access_list'
            '/add/user/%s/?authMethod=%s' %
            (self.experiment2.id, self.user1.username, localdb_auth_key))
        self.assertEqual(response.status_code, 403)

        # user2 *IS* allowed to modify acls for experiment1, since they are part
        # of an owning group (we add then remove access for user3)
        response = self.client1.get(
            '/experiment/control_panel/%i/access_list'
            '/add/user/%s/?authMethod=%s' %
            (self.experiment1.id, self.user3.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)
        response = self.client1.get(
            '/experiment/control_panel/%i/access_list'
            '/remove/user/%s/?authMethod=%s' %
            (self.experiment1.id, self.user3.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'OK')

        # test add non-existent user
        non_existant = 'test_boozer'
        response = self.client1.get(
            '/experiment/control_panel/%i/access_list'
            '/add/user/%s/?authMethod=%s' %
            (self.experiment1.id, non_existant, localdb_auth_key))

        self.assertContains(response, 'User %s does not exist' % non_existant)

        # test add to non existant experiment

        # Note: Ideally we'd like to check for error message, but we
        # can't hit it with the decorator in place.  However,
        # currently we check for a 403 (forbidden) error, as the
        # 'experiment_ownership_required' decorator simply checks if
        # the experiment_id appears in the specified user's ACL, and
        # assumes that the absence of the experiment_id means that the
        # experiment exists but the user doesn't have access to
        # it. This could possibly be changed to a 404 error.

        response = self.client1.get(
            '/experiment/control_panel/%i/access_list'
            '/add/user/%s/?authMethod=%s' %
            (9999, self.user1.username, localdb_auth_key))
        self.assertEqual(response.status_code, 403)

        self.client1.logout()

        # now check user2's permissions
        login = self.client2.login(username=self.user2.username,
                                   password='******')
        self.assertTrue(login)

        # user2 should be able to see experiment1 now
        response = self.client2.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be also able to see experiment2
        response = self.client2.get('/experiment/view/%i/' %
                                    (self.experiment2.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be allowed to see experiment3 as it's public
        response = self.client2.get('/experiment/view/%i/' %
                                    (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be able to add user3 to group1 (experiment1)
        response = self.client2.get(
            '/group/%i/add/%s/?isAdmin=false&authMethod=%s' %
            (group.id, self.user3.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        self.client2.logout()

        # now check user3's permissions
        login = self.client3.login(username=self.user3.username,
                                   password='******')
        self.assertTrue(login)

        # user3 should be able to see experiment1 via his group permissions
        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user3 should not be able to see experiment2
        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # user3 should be able to see experiment3
        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user3 should not be able to add another user4 to group1
        response = self.client3.get(
            '/group/%i/add/%s/?isAdmin=false&authMethod=%s' %
            (group.id, 'testuser4', localdb_auth_key))
        self.assertEqual(response.status_code, 403)

        self.client3.logout()

        # ok, now do some tricky stuff
        today = datetime.datetime.today()
        yesterday = today - datetime.timedelta(days=1)
        tomorrow = today + datetime.timedelta(days=1)

        url = ("/experiment/control_panel/%i/access_list"
               "/change/user/%s/?authMethod=%s")

        login = self.client1.login(username=self.user1.username,
                                   password='******')
        self.assertTrue(login)

        # remove user3 from group1
        response = self.client1.get('/group/%i/remove/%s/' %
                                    (group.id, self.user3.username))
        self.assertEqual(response.status_code, 200)

        # add user3 to experiment1
        response = self.client1.get(
            '/experiment/control_panel/%i/access_list'
            '/add/user/%s/?authMethod=%s' %
            (self.experiment1.id, self.user3.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, '<div class="access_list_user')

        # give user3 read permissions for experiment1 effective TOMORROW
        response = self.client1.post(
            url % (self.experiment1.id, self.user3.username, localdb_auth_key),
            {
                'canRead': True,
                'effectiveDate_year': tomorrow.year,
                'effectiveDate_month': tomorrow.month,
                'effectiveDate_day': tomorrow.day,
            })
        # logger.debug('[1] response =' + str(response))
        self.assertEqual(response.status_code, 302)

        # check permissions for user3
        login = self.client3.login(username=self.user3.username,
                                   password='******')
        self.assertTrue(login)

        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # change effective date to TODAY
        response = self.client1.post(
            url % (self.experiment1.id, self.user3.username, localdb_auth_key),
            {
                'canRead': True,
                'effectiveDate_year': today.year,
                'effectiveDate_month': today.month,
                'effectiveDate_day': today.day,
            })
        self.assertEqual(response.status_code, 302)

        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # change effictive date to YESTERDAY
        self.client1.post(
            url % (self.experiment1.id, self.user3.username, localdb_auth_key),
            {
                'canRead': True,
                'effectiveDate_year': yesterday.year,
                'effectiveDate_month': yesterday.month,
                'effectiveDate_day': yesterday.day,
            })

        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to TOMORROW
        self.client1.post(
            url % (self.experiment1.id, self.user3.username, localdb_auth_key),
            {
                'canRead': True,
                'expiryDate_year': tomorrow.year,
                'expiryDate_month': tomorrow.month,
                'expiryDate_day': tomorrow.day,
            })

        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to TODAY
        self.client1.post(
            url % (self.experiment1.id, self.user3.username, localdb_auth_key),
            {
                'canRead': True,
                'expiryDate_year': today.year,
                'expiryDate_month': today.month,
                'expiryDate_day': today.day,
            })

        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to YESTERDAY
        self.client1.post(
            url % (self.experiment1.id, self.user3.username, localdb_auth_key),
            {
                'canRead': True,
                'expiryDate_year': yesterday.year,
                'expiryDate_month': yesterday.month,
                'expiryDate_day': yesterday.day,
            })

        response = self.client3.get('/experiment/view/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # remove user3 from experiment1 again
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/' %
                                    (self.experiment1.id, self.user3.username))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'OK')

        # try again, see if it falls over
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/' %
                                    (self.experiment1.id, self.user3.username))
        self.assertEqual(
            response.content,
            'The user %s does not have access to this experiment.' %
            self.user3.username)

        # try to remove from a non-existant experiment
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/' %
                                    (9999, self.user3.username))
        self.assertEqual(response.status_code, 403)

        # try to remove the only owner
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/' %
                                    (self.experiment1.id, self.user1.username))
        self.assertEqual(
            response.content, 'All experiments must have at least '
            'one user as owner. Add an '
            'additional owner first before '
            'removing this one.')

        # create a group2 and add it to experiment1
        response = self.client1.get(
            '/experiment/control_panel'
            '/create/group/?group=%s&authMethod=localdb' % ('group2'))
        self.assertEqual(response.status_code, 200)

        # give group2 read-only access to experiment1
        response = self.client1.get(
            '/experiment/control_panel/%i'
            '/access_list/add/group/%s/?canRead=true'
            '&canWrite=false&canDelete=false&isOwner=false' %
            (self.experiment1.id, 'group2'))
        self.assertEqual(response.status_code, 200)

        # add user3 as admin to group2
        self.group2 = Group.objects.get(name='group2')
        response = self.client1.get(
            '/group/%i/add/%s/?isAdmin=true&authMethod=%s' %
            (self.group2.id, self.user3.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # as user3, try to add myself as an owner of the experiment1
        response = self.client3.get(
            '/experiment/control_panel/%i/access_list'
            '/add/user/%s/?authMethod=%s&canRead=true'
            '&canWrite=true&canDelete=false&'
            'isOwner=true' %
            (self.experiment1.id, self.user3.username, localdb_auth_key))
        # this should fail since the group2, of which user3 is a member, is
        # not an 'owner' group, just a read-only group
        self.assertEqual(response.status_code, 403)

        # as user3, attempt to remove user1 as the owner of experiment1
        response = self.client3.get(
            '/experiment/control_panel/%i/access_list'
            '/remove/user/%s/?authMethod=%s' %
            (self.experiment1.id, self.user1.username, localdb_auth_key))
        # this should fail since the group2, of which user3 is a member, is
        # not an 'owner' group, just a read-only group
        self.assertEqual(response.status_code, 403)

        # as user1, add user3 as an owner of experiment1
        response = self.client1.get(
            '/experiment/control_panel/%i/access_list'
            '/add/user/%s/?authMethod=%s&canRead=true'
            '&canWrite=true&canDelete=false&'
            'isOwner=true' %
            (self.experiment1.id, self.user3.username, localdb_auth_key))
        # since user1 is an owner user of experiment1, we can add additional
        # owner users to the experiment
        self.assertEqual(response.status_code, 200)

        # as user3 (now an owner), attempt to remove user1 as the owner of
        # experiment1, leaving user3 as the sole owner
        response = self.client3.get(
            '/experiment/control_panel/%i/access_list'
            '/remove/user/%s/?authMethod=%s' %
            (self.experiment1.id, self.user1.username, localdb_auth_key))
        # this should now succeed since both user3 and user1 are owners of
        # experiment1, and user3 is allowed to remove other owners (unless they
        # are the only owner user)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'OK')

        # as user3 (now the only owner), attempts to remove myself as the owner
        # of experiment1
        response = self.client3.get(
            '/experiment/control_panel/%i/access_list'
            '/remove/user/%s/?authMethod=%s' %
            (self.experiment1.id, self.user3.username, localdb_auth_key))
        # this should fail with an error since every experiment must have at
        # least one user owner
        self.assertEqual(
            response.content, 'All experiments must have at least one user as '
            'owner. Add an additional owner first before '
            'removing this one.')

        self.client1.logout()
        self.client3.logout()

    def testWriteAccess(self):
        # without logging in the request should be redirected
        response = self.client1.get('/experiment/edit/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 302)

        # now check access for user1
        login = self.client1.login(username=self.user1.username,
                                   password='******')
        self.assertTrue(login)
        response = self.client1.get('/experiment/edit/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # write access has not been granted for experiment2
        response = self.client1.get('/experiment/edit/%i/' %
                                    (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # neither experiment3 which is public
        response = self.client1.get('/experiment/edit/%i/' %
                                    (self.experiment3.id))
        self.assertEqual(response.status_code, 403)

        # create a group 'group1w' with write permissions
        response = self.client1.get(
            '/experiment/control_panel'
            '/create/group/?group=%s&authMethod=localdb' % ('group1w'))
        self.assertEqual(response.status_code, 200)

        response = self.client1.get(
            '/experiment/control_panel/%i'
            '/access_list/add/group/%s/?canRead=true'
            '&canWrite=true&canDelete=false&isOwner=undefined' %
            (self.experiment1.id, 'group1w'))
        self.assertEqual(response.status_code, 200)

        # add user2 to 'group1w' which gives him write permissions
        group = Group.objects.get(name='group1w')
        response = self.client1.get(
            '/group/%i/add/%s/?isAdmin=false&authMethod=%s' %
            (group.id, self.user2.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # add user3 explicitly to experiment1
        response = self.client1.get(
            '/experiment/control_panel/%i/access_list'
            '/add/user/%s/?authMethod=%s&canRead=true'
            '&canWrite=true' %
            (self.experiment1.id, self.user3.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # check newly created permissions for user2 and user3
        response = self.client2.get('/experiment/edit/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 302)

        response = self.client3.get('/experiment/edit/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 302)

        login = self.client2.login(username=self.user2.username,
                                   password='******')
        self.assertTrue(login)

        login = self.client3.login(username=self.user3.username,
                                   password='******')
        self.assertTrue(login)

        # response = self.client2.get('/experiment/edit/%i/' % (self.experiment1.id))
        # self.assertEqual(response.status_code, 200)

        response = self.client3.get('/experiment/edit/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # now the fancy stuff with timestamps
        today = datetime.datetime.today()
        yesterday = today - datetime.timedelta(days=1)
        tomorrow = today + datetime.timedelta(days=1)

        url = '/experiment/control_panel/%i/access_list/change/group/%i/'

        # give group 'group1w' write permissions for experiment1 effictive TOMORROW
        response = self.client1.post(
            url % (self.experiment1.id, group.id), {
                'canRead': True,
                'canWrite': True,
                'effectiveDate_year': tomorrow.year,
                'effectiveDate_month': tomorrow.month,
                'effectiveDate_day': tomorrow.day,
            })

        self.assertEqual(response.status_code, 302)

        response = self.client2.get('/experiment/edit/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # change effictive date to TODAY
        response = self.client1.post(
            url % (self.experiment1.id, group.id), {
                'canRead': True,
                'canWrite': True,
                'effectiveDate_year': today.year,
                'effectiveDate_month': today.month,
                'effectiveDate_day': today.day,
            })
        self.assertEqual(response.status_code, 302)

        # now user2 should have write access again
        response = self.client2.get('/experiment/edit/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # repeat all the tests with timestamps for user3
        url = '/experiment/control_panel/%i/access_list/change/user/%s/'

        # give user3 write permissions for experiment1 effictive TOMORROW
        response = self.client1.post(
            url % (self.experiment1.id, self.user3.username), {
                'canRead': True,
                'canWrite': True,
                'effectiveDate_year': tomorrow.year,
                'effectiveDate_month': tomorrow.month,
                'effectiveDate_day': tomorrow.day,
            })
        self.assertEqual(response.status_code, 302)

        response = self.client3.get('/experiment/edit/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # change effictive date to TODAY
        response = self.client1.post(
            url % (self.experiment1.id, self.user3.username), {
                'canRead': True,
                'canWrite': True,
                'effectiveDate_year': today.year,
                'effectiveDate_month': today.month,
                'effectiveDate_day': today.day,
            })
        self.assertEqual(response.status_code, 302)

        # now user3 should have write access again
        response = self.client3.get('/experiment/edit/%i/' %
                                    (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        self.client1.logout()
        self.client2.logout()
        self.client3.logout()

    def testCantEditLockedExperiment(self):
        login = self.client3.login(username=self.user3.username,
                                   password='******')
        self.assertTrue(login)

        # user3 has acl to write to experiment3
        acl = ObjectACL(
            pluginId=django_user,
            entityId=str(self.user3.id),
            content_object=self.experiment3,
            canRead=True,
            canWrite=True,
            aclOwnershipType=ObjectACL.OWNER_OWNED,
        )
        acl.save()

        response = self.client3.get('/experiment/edit/%i/' %
                                    (self.experiment3.id))
        self.assertEqual(response.status_code, 403)

        response = self.client3.post(
            '/experiment/edit/%i/' % (self.experiment3.id), {
                'anything': True,
            })
        self.assertEqual(response.status_code, 403)

        acl.delete()
        self.client3.logout()

    def testOwnedExperiments(self):
        user = AnonymousUser()

        # not logged in
        class MockRequest:
            pass

        request = MockRequest()
        request.user = user
        num_exps = Experiment.safe.owned(request.user).count()
        self.assertEqual(num_exps, 0)

    def testCantAddTokenuserToGroups(self):
        from django.conf import settings
        login = self.client3.login(username=self.user3.username,
                                   password='******')
        self.assertTrue(login)
        g = Group()
        g.save()
        self.client3.get('/group/%s/%s/' % (g.id, settings.TOKEN_USERNAME))
        self.assertEqual(0, g.user_set.count())  # user should not be added
예제 #18
0
class UploadTestCase(TestCase):

    def setUp(self):
        from os import path, mkdir
        from tempfile import mkdtemp

        user = '******'
        pwd = 'secret'
        email = ''
        self.user = User.objects.create_user(user, email, pwd)

        self.userProfile = UserProfile(user=self.user)

        self.test_dir = mkdtemp()

        self.exp = Experiment(title='test exp1',
                institution_name='monash', created_by=self.user)
        self.exp.save()

        acl = ExperimentACL(
            pluginId=django_user,
            entityId=str(self.user.id),
            experiment=self.exp,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ExperimentACL.OWNER_OWNED,
            )
        acl.save()

        self.dataset = \
            Dataset(description='dataset description...',
                           experiment=self.exp)
        self.dataset.save()

        self.experiment_path = path.join(settings.FILE_STORE_PATH,
                str(self.dataset.experiment.id))

        self.dataset_path = path.join(self.experiment_path,
                                      str(self.dataset.id))

        if not path.exists(self.experiment_path):
            mkdir(self.experiment_path)
        if not path.exists(self.dataset_path):
            mkdir(self.dataset_path)

        # write test file

        self.filename = 'testfile.txt'

        self.f1 = open(path.join(self.test_dir, self.filename), 'w')
        self.f1.write('Test file 1')
        self.f1.close()

        self.f1_size = path.getsize(path.join(self.test_dir,
                                    self.filename))

        self.f1 = open(path.join(self.test_dir, self.filename), 'r')

    def tearDown(self):
        from shutil import rmtree

        self.f1.close()
        rmtree(self.test_dir)
        rmtree(self.dataset_path)
        rmtree(self.experiment_path)
        self.exp.delete()

    def testFileUpload(self):
        from os import path

        c = Client()
        c.login(username='******', password='******')
        session_id = c.session.session_key

        response = c.post('/upload/' + str(self.dataset.id) + '/',
            {'Filedata': self.f1, 'session_id': session_id})

        test_files_db = \
            Dataset_File.objects.filter(dataset__id=self.dataset.id)

        self.assertTrue(path.exists(path.join(self.dataset_path,
                        self.filename)))
        self.assertTrue(self.dataset.id == 1)
        self.assertTrue(test_files_db[0].url == 'tardis://testfile.txt')

    def testUploadComplete(self):
        from django.http import QueryDict, HttpRequest
        from tardis.tardis_portal.views import upload_complete
        data = [('filesUploaded', '1'), ('speed', 'really fast!'),
                ('allBytesLoaded', '2'), ('errorCount', '0')]
        post = QueryDict('&'.join(['%s=%s' % (k, v) for (k, v) in
                         data]))
        request = HttpRequest()
        request.POST = post
        response = upload_complete(request)
        self.assertTrue('<p>Number: 1</p>' in response.content)
        self.assertTrue('<p>Errors: 0</p>' in response.content)
        self.assertTrue('<p>Bytes: 2</p>' in response.content)
        self.assertTrue('<p>Speed: really fast!</p>'
                        in response.content)
예제 #19
0
class TarDownloadTestCase(TestCase):

    def setUp(self):
        # create user
        self.testuser = User(username='******')
        self.testuser.save()

        # create test experiment
        self.exp = Experiment(title='tar download test' * 15,
                              created_by=self.testuser,
                              public_access=Experiment.PUBLIC_ACCESS_FULL)
        self.exp.save()

        # create test dataset
        self.ds = self.exp.datasets.create(
            description="testing tar download dataset")

        datafile_content = "\n".join(['some data %d' % i
                                      for i in range(1000)])
        filesize = len(datafile_content)
        md5sum = hashlib.md5(datafile_content).hexdigest()
        # create test datafiles and datafile objects
        self.dfs = []
        for i in range(20):
            df = self.ds.datafile_set.create(
                filename='testfile%d.txt' % i,
                mimetype='text/plain',
                size=filesize,
                md5sum=md5sum,
                directory='/'.join([
                    'testdir%d' % i
                    for i in range(i, i + 4)
                ]))
            df.file_object = StringIO(datafile_content)
            df.refresh_from_db()
            self.dfs.append(df)

        # mock client
        self.client = Client()

    def tearDown(self):
        # delete created objects and files

        [ds.delete() for ds in self.exp.datasets.all()]
        self.exp.delete()

    def test_tar_experiment_download(self):
        self.assertTrue(all(df.verified for df in self.dfs))
        response = self.client.get(reverse(
            'tardis.tardis_portal.download.streaming_download_experiment',
            args=(self.exp.id, 'tar')))
        with NamedTemporaryFile('w') as tarfile:
            for c in response.streaming_content:
                tarfile.write(c)
            tarfile.flush()
            self.assertEqual(int(response['Content-Length']),
                             os.stat(tarfile.name).st_size)
            tf = TarFile(tarfile.name)
            if settings.EXP_SPACES_TO_UNDERSCORES:
                exp_title = self.exp.title.replace(' ', '_')
            else:
                exp_title = self.exp.title
            exp_title = quote(exp_title,
                              safe=settings.SAFE_FILESYSTEM_CHARACTERS)
            for df in self.dfs:
                full_path = os.path.join(
                    exp_title,
                    quote(self.ds.description,
                          safe=settings.SAFE_FILESYSTEM_CHARACTERS),
                    df.directory, df.filename)
                # docker has a file path limit of ~240 characters
                if os.environ.get('DOCKER_BUILD', 'false') != 'true':
                    tf.extract(full_path, '/tmp')
                    self.assertEqual(
                        os.stat(os.path.join('/tmp', full_path)).st_size,
                        int(df.size))
예제 #20
0
class DownloadTestCase(TestCase):

    def setUp(self):
        # create a test user
        self.user = User.objects.create_user(username='******',
                                             email='',
                                             password='******')

        # create a public experiment
        self.experiment1 = Experiment(title='Experiment 1',
                                      created_by=self.user,
                                      public=True)
        self.experiment1.save()

        # create a non-public experiment
        self.experiment2 = Experiment(title='Experiment 2',
                                      created_by=self.user,
                                      public=False)
        self.experiment2.save()

        # dataset1 belongs to experiment1
        self.dataset1 = Dataset(experiment=self.experiment1)
        self.dataset1.save()

        # dataset2 belongs to experiment2
        self.dataset2 = Dataset(experiment=self.experiment2)
        self.dataset2.save()

        # absolute path first
        filename = 'testfile.txt'
        self.dest1 = abspath(join(settings.FILE_STORE_PATH, '%s/%s/'
                                  % (self.experiment1.id,
                                  self.dataset1.id)))
        self.dest2 = abspath(join(settings.FILE_STORE_PATH,
                                '%s/%s/'
                                  % (self.experiment2.id,
                                  self.dataset2.id)))
        if not exists(self.dest1):
            makedirs(self.dest1)
        if not exists(self.dest2):
            makedirs(self.dest2)

        testfile1 = abspath(join(self.dest1, filename))
        f = open(testfile1, 'w')
        f.write("Hello World!\n")
        f.close()

        testfile2 = abspath(join(self.dest2, filename))
        f = open(testfile2, 'w')
        f.write("Hello World!\n")
        f.close()

        self.dataset_file1 = Dataset_File(dataset=self.dataset1,
                                          filename=filename,
                                          protocol='tardis',
                                          url='tardis://%s' % filename)
        self.dataset_file1.save()

        self.dataset_file2 = Dataset_File(dataset=self.dataset2,
                                          filename=basename(filename),
                                          protocol='tardis',
                                          url='tardis://%s' % filename)
        self.dataset_file2.save()

    def tearDown(self):
        self.user.delete()
        self.experiment1.delete()
        self.experiment2.delete()
        rmtree(self.dest1)
        rmtree(self.dest2)

    def testDownload(self):
        client = Client()

        # check download for experiment1
        response = client.get('/download/experiment/%i/zip/' % self.experiment1.id)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="experiment%s-complete.zip"'
                         % self.experiment1.id)
        self.assertEqual(response.status_code, 200)

        # check download of file1
        response = client.get('/download/datafile/%i/' % self.dataset_file1.id)

        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s"'
                         % self.dataset_file2.filename)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Hello World!\n')

        # requesting file2 should be forbidden...
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 403)

        # check dataset1 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [self.dataset1.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 200)

        # check dataset2 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [self.dataset2.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 403)

        # check datafile1 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [],
                                'datafile': [self.dataset_file1.id]})
        self.assertEqual(response.status_code, 200)

        # check datafile2 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [],
                                'datafile': [self.dataset_file2.id]})
        self.assertEqual(response.status_code, 403)

    def testDatasetFile(self):

        # check registered text file for physical file meta information
        df = Dataset_File.objects.get(pk=self.dataset_file1.id)

        try:
            from magic import Magic
            self.assertEqual(df.mimetype, 'text/plain; charset=us-ascii')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(df.size, str(13))
        self.assertEqual(df.md5sum, '8ddd8be4b179a529afa5f2ffae4b9858')

        # now check a JPG file
        filename = join(abspath(dirname(__file__)),
                        '../static/images/ands-logo-hi-res.jpg')

        dataset = Dataset.objects.get(pk=self.dataset1.id)

        pdf1 = Dataset_File(dataset=dataset,
                            filename=basename(filename),
                            url='file://%s' % filename,
                            protocol='file')
        pdf1.save()
        try:
            from magic import Magic
            self.assertEqual(pdf1.mimetype, 'image/jpeg')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(pdf1.size, str(14232))
        self.assertEqual(pdf1.md5sum, 'c450d5126ffe3d14643815204daf1bfb')

        # now check that we can override the physical file meta information
        pdf2 = Dataset_File(dataset=dataset,
                            filename=basename(filename),
                            url='file://%s' % filename,
                            protocol='file',
                            mimetype='application/vnd.openxmlformats-officedocument.presentationml.presentation',
                            size=str(0),
                            md5sum='md5sum')
        pdf2.save()
        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(pdf2.size, str(0))
        self.assertEqual(pdf2.md5sum, 'md5sum')

        pdf2.mimetype = ''
        pdf2.save()

        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/pdf')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
예제 #21
0
class DownloadTestCase(TestCase):

    def setUp(self):
        # create a test user
        self.user = User.objects.create_user(username='******',
                                             email='',
                                             password='******')

        # create a public experiment
        self.experiment1 = Experiment(title='Experiment 1',
                                      created_by=self.user,
                                      public_access=Experiment.PUBLIC_ACCESS_FULL)
        self.experiment1.save()

        # create a non-public experiment
        self.experiment2 = Experiment(title='Experiment 2',
                                      created_by=self.user,
                                      public_access=Experiment.PUBLIC_ACCESS_NONE)
        self.experiment2.save()

        # dataset1 belongs to experiment1
        self.dataset1 = Dataset()
        self.dataset1.save()
        self.dataset1.experiments.add(self.experiment1)
        self.dataset1.save()


        # dataset2 belongs to experiment2
        self.dataset2 = Dataset()
        self.dataset2.save()
        self.dataset2.experiments.add(self.experiment2)
        self.dataset2.save()

        # absolute path first
        filename1 = 'testfile.txt'
        filename2 = 'testfile.tiff'
        self.dest1 = abspath(join(settings.FILE_STORE_PATH, '%s/%s/'
                                  % (self.experiment1.id,
                                  self.dataset1.id)))
        self.dest2 = abspath(join(settings.FILE_STORE_PATH,
                                '%s/%s/'
                                  % (self.experiment2.id,
                                  self.dataset2.id)))
        if not exists(self.dest1):
            makedirs(self.dest1)
        if not exists(self.dest2):
            makedirs(self.dest2)

        testfile1 = abspath(join(self.dest1, filename1))
        f = open(testfile1, 'w')
        f.write("Hello World!\n")
        f.close()

        testfile2 = abspath(join(self.dest2, filename2))
        if IMAGEMAGICK_AVAILABLE:
            with Image(filename='logo:') as img:
                img.format = 'tiff'
                img.save(filename=testfile2)
        else:
            # Apparently ImageMagick isn't installed...
            # Write a "fake" TIFF file
            f = open(testfile2, 'w')
            f.write("II\x2a\x00")
            f.close()


        size, sha512sum = get_size_and_sha512sum(testfile1)
        self.dataset_file1 = Dataset_File(dataset=self.dataset1,
                                          filename=filename1,
                                          protocol='',
                                          size=size,
                                          sha512sum=sha512sum,
                                          url='%d/%d/%s'
                                              % (self.experiment1.id,
                                                 self.dataset1.id,
                                                 filename1))
        self.dataset_file1.verify()
        self.dataset_file1.save()

        size, sha512sum = get_size_and_sha512sum(testfile2)
        self.dataset_file2 = Dataset_File(dataset=self.dataset2,
                                          filename=basename(filename2),
                                          protocol='',
                                          size=size,
                                          sha512sum=sha512sum,
                                          url='%d/%d/%s'
                                            % (self.experiment2.id,
                                               self.dataset2.id,
                                               filename2))
        self.dataset_file2.verify()
        self.dataset_file2.save()

    def tearDown(self):
        self.user.delete()
        self.experiment1.delete()
        self.experiment2.delete()
        rmtree(self.dest1)
        rmtree(self.dest2)

    def testView(self):
        client = Client()

        # check view of file1
        response = client.get('/datafile/view/%i/' % self.dataset_file1.id)

        self.assertEqual(response['Content-Disposition'],
                         'inline; filename="%s"'
                         % self.dataset_file1.filename)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Hello World!\n')

        # check view of file2
        response = client.get('/datafile/view/%i/' % self.dataset_file2.id)
        # Should be forbidden
        self.assertEqual(response.status_code, 403)

        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        # check view of file2 again
        response = client.get('/datafile/view/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 200)

        # The following behaviour relies on ImageMagick
        if IMAGEMAGICK_AVAILABLE:
            # file2 should have a ".png" filename
            self.assertEqual(response['Content-Disposition'],
                             'inline; filename="%s"'
                             % (self.dataset_file2.filename+'.png'))
            # file2 should be a PNG
            self.assertEqual(response['Content-Type'], 'image/png')
            png_signature = "\x89PNG\r\n\x1a\n"
            self.assertEqual(response.content[0:8], png_signature)
        else:
            # file2 should have a ".tiff" filename
            self.assertEqual(response['Content-Disposition'],
                             'inline; filename="%s"'
                             % (self.dataset_file2.filename))
            # file2 should be a TIFF
            self.assertEqual(response['Content-Type'], 'image/tiff')
            tiff_signature = "II\x2a\x00"
            self.assertEqual(response.content[0:4], tiff_signature)

    def _check_tar_file(self, content, rootdir, datafiles):
        # It should be a zip file
        with NamedTemporaryFile('w') as tempfile:
            tempfile.write(content)
            tempfile.flush()
            with open(tempfile.name, 'r') as zipread:
                # It should be a zip file (all of which start with "PK")
                expect(zipread.read(2)).to_equal('PK')
            expect(is_zipfile(tempfile.name)).to_be_truthy()
            with ZipFile(tempfile.name, 'r') as zf:
                expect(len(zf.namelist())).to_equal(len(datafiles))
                for df in datafiles:
                    filename = join(rootdir, str(df.dataset.id), df.filename)
                    expect(filename in zf.namelist()).to_be_truthy()

    def _check_zip_file(self, content, rootdir, datafiles):
        # It should be a zip file
        with NamedTemporaryFile('w') as tempfile:
            tempfile.write(content)
            tempfile.flush()
            with open(tempfile.name, 'r') as zipread:
                # It should be a zip file (all of which start with "PK")
                expect(zipread.read(2)).to_equal('PK')
            expect(is_zipfile(tempfile.name)).to_be_truthy()
            zf = ZipFile(tempfile.name, 'r')
            expect(len(zf.namelist())).to_equal(len(datafiles))
            for df in datafiles:
                filename = join(rootdir, str(df.dataset.id), df.filename)
                expect(filename in zf.namelist()).to_be_truthy()
            zf.close()


    def testDownload(self):
        client = Client()

        # check download for experiment1
        response = client.get('/download/experiment/%i/zip/' % self.experiment1.id)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="experiment%s-complete.zip"'
                         % self.experiment1.id)
        self.assertEqual(response.status_code, 200)
        self._check_zip_file(response.content, str(self.experiment1.id),
                             reduce(lambda x, y: x + y,
                                    [ds.dataset_file_set.all() \
                                     for ds in self.experiment1.datasets.all()]))

        # check download of file1
        response = client.get('/download/datafile/%i/' % self.dataset_file1.id)

        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s"'
                         % self.dataset_file1.filename)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Hello World!\n')

        # requesting file2 should be forbidden...
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 403)

        # check dataset1 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [self.dataset1.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 200)
        self._check_zip_file(response.content, 'datasets',
                             self.dataset1.dataset_file_set.all())

        # check dataset2 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [self.dataset2.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 403)

        # check datafile1 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [],
                                'datafile': [self.dataset_file1.id]})
        self.assertEqual(response.status_code, 200)
        self._check_zip_file(response.content, 'datasets', [self.dataset_file1])

        # check datafile2 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [],
                                'datafile': [self.dataset_file2.id]})
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to "metadata only"
        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_METADATA
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        # Metadata-only means "no file access"!
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to public
        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 200)
        # This should be a TIFF (which often starts with "II\x2a\x00")
        self.assertEqual(response['Content-Type'], 'image/tiff')
        self.assertEqual(response.content[0:4], "II\x2a\x00")


    def testDatasetFile(self):

        # check registered text file for physical file meta information
        df = Dataset_File.objects.get(pk=self.dataset_file1.id)

        try:
            from magic import Magic
            self.assertEqual(df.mimetype, 'text/plain; charset=us-ascii')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(df.size, str(13))
        self.assertEqual(df.md5sum, '8ddd8be4b179a529afa5f2ffae4b9858')

        # now check a JPG file
        filename = abspath(join(dirname(__file__),
                                '../static/images/ands-logo-hi-res.jpg'))

        dataset = Dataset.objects.get(pk=self.dataset1.id)

        size, sha512sum = get_size_and_sha512sum(filename)
        pdf1 = Dataset_File(dataset=dataset,
                            filename=basename(filename),
                            size=str(size),
                            sha512sum=sha512sum,
                            url='file://%s' % filename,
                            protocol='file')
        pdf1.verify()
        pdf1.save()
        try:
            from magic import Magic
            self.assertEqual(pdf1.mimetype, 'image/jpeg')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(pdf1.size, str(14232))
        self.assertEqual(pdf1.md5sum, 'c450d5126ffe3d14643815204daf1bfb')

        # now check that we can override the physical file meta information
        pdf2 = Dataset_File(dataset=dataset,
                            filename=basename(filename),
                            url='file://%s' % filename,
                            protocol='file',
                            mimetype='application/vnd.openxmlformats-officedocument.presentationml.presentation',
                            size=str(0),
                            # Empty string always has the same hash
                            sha512sum='cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e')
        pdf2.save()
        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
        self.assertEqual(pdf2.size, str(0))
        self.assertEqual(pdf2.md5sum, '')

        pdf2.mimetype = ''
        pdf2.save()

        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/pdf')
        except:
            # XXX Test disabled becuse lib magic can't be loaded
            pass
예제 #22
0
class DownloadTestCase(TestCase):
    def setUp(self):
        # create a test user
        self.user = User.objects.create_user(username='******',
                                             email='',
                                             password='******')

        # create a public experiment
        self.experiment1 = Experiment(
            title='Experiment 1',
            created_by=self.user,
            public_access=Experiment.PUBLIC_ACCESS_FULL)
        self.experiment1.save()

        # create a non-public experiment
        self.experiment2 = Experiment(
            title='Experiment 2',
            created_by=self.user,
            public_access=Experiment.PUBLIC_ACCESS_NONE)
        self.experiment2.save()

        # dataset1 belongs to experiment1
        self.dataset1 = Dataset(description='dangerous;name')
        self.dataset1.save()
        self.dataset1.experiments.add(self.experiment1)
        self.dataset1.save()

        # dataset2 belongs to experiment2
        self.dataset2 = Dataset(description='terrible\nname')
        self.dataset2.save()
        self.dataset2.experiments.add(self.experiment2)
        self.dataset2.save()

        # absolute path first
        filename1 = 'testfile.txt'
        filename2 = 'testfile.tiff'
        self.dest1 = abspath(
            join(settings.FILE_STORE_PATH,
                 '%s/%s/' % (self.experiment1.id, self.dataset1.id)))
        self.dest2 = abspath(
            join(settings.FILE_STORE_PATH,
                 '%s/%s/' % (self.experiment2.id, self.dataset2.id)))
        if not exists(self.dest1):
            makedirs(self.dest1)
        if not exists(self.dest2):
            makedirs(self.dest2)

        testfile1 = abspath(join(self.dest1, filename1))
        f = open(testfile1, 'w')
        f.write("Hello World!\n")
        f.close()

        testfile2 = abspath(join(self.dest2, filename2))
        _generate_test_image(testfile2)

        self.datafile1 = self._build_datafile(testfile1, filename1,
                                              self.dataset1)

        self.datafile2 = self._build_datafile(testfile2, filename2,
                                              self.dataset2)

    def _build_datafile(self,
                        testfile,
                        filename,
                        dataset,
                        checksum=None,
                        size=None,
                        mimetype=''):
        filesize, sha512sum = get_size_and_sha512sum(testfile)
        datafile = DataFile(dataset=dataset,
                            filename=filename,
                            mimetype=mimetype,
                            size=size if size is not None else filesize,
                            sha512sum=(checksum if checksum else sha512sum))
        datafile.save()
        dfo = DataFileObject(datafile=datafile,
                             storage_box=datafile.get_default_storage_box())
        dfo.save()
        with open(testfile, 'r') as sourcefile:
            dfo.file_object = sourcefile
        return DataFile.objects.get(pk=datafile.pk)

    def tearDown(self):
        self.user.delete()
        self.experiment1.delete()
        self.experiment2.delete()
        rmtree(self.dest1)
        rmtree(self.dest2)

    def testView(self):
        client = Client()

        # check view of file1
        response = client.get('/datafile/view/%i/' % self.datafile1.id)

        self.assertEqual(response['Content-Disposition'],
                         'inline; filename="%s"' % self.datafile1.filename)
        self.assertEqual(response.status_code, 200)
        response_content = ""
        for c in response.streaming_content:
            response_content += c
        self.assertEqual(response_content, 'Hello World!\n')

        # check view of file2
        response = client.get('/datafile/view/%i/' % self.datafile2.id)
        # Should be forbidden
        self.assertEqual(response.status_code, 403)

        self.experiment2.public_access = Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        # check view of file2 again
        response = client.get('/datafile/view/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 200)

        # The following behaviour relies on ImageMagick
        if IMAGEMAGICK_AVAILABLE:
            # file2 should have a ".png" filename
            self.assertEqual(
                response['Content-Disposition'],
                'inline; filename="%s"' % (self.datafile2.filename + '.png'))
            # file2 should be a PNG
            self.assertEqual(response['Content-Type'], 'image/png')
            png_signature = "\x89PNG\r\n\x1a\n"
            self.assertEqual(response.content[0:8], png_signature)
        else:
            # file2 should have a ".tiff" filename
            self.assertEqual(
                response['Content-Disposition'],
                'inline; filename="%s"' % (self.datafile2.filename))
            # file2 should be a TIFF
            self.assertEqual(response['Content-Type'], 'image/tiff')
            tiff_signature = "II\x2a\x00"
            self.assertEqual(response.content[0:4], tiff_signature)

    def _check_tar_file(self,
                        content,
                        rootdir,
                        datafiles,
                        simpleNames=False,
                        noTxt=False):
        with NamedTemporaryFile('w') as tempfile:
            for c in content:
                tempfile.write(c)
            tempfile.flush()
            if getsize(tempfile.name) > 0:
                expect(is_tarfile(tempfile.name)).to_be_truthy()
                try:
                    tf = TarFile(tempfile.name, 'r')
                    self._check_names(datafiles, tf.getnames(), rootdir,
                                      simpleNames, noTxt)
                finally:
                    tf.close()
            else:
                self._check_names(datafiles, [], rootdir, simpleNames, noTxt)

    def _check_zip_file(self,
                        content,
                        rootdir,
                        datafiles,
                        simpleNames=False,
                        noTxt=False):
        with NamedTemporaryFile('w') as tempfile:
            for c in content:
                tempfile.write(c)
            tempfile.flush()
            # It should be a zip file
            expect(is_zipfile(tempfile.name)).to_be_truthy()
            try:
                zf = ZipFile(tempfile.name, 'r')
                self._check_names(datafiles, zf.namelist(), rootdir,
                                  simpleNames, noTxt)
            finally:
                zf.close()

    def _check_names(self, datafiles, names, rootdir, simpleNames, noTxt):
        # SimpleNames says if we expect basenames or pathnames
        # NoTxt says if we expect '.txt' files to be filtered out
        for name in names:
            self.assertNotRegexpMatches(name, '\n|;')
        expect(len(names)).to_equal(len(datafiles))

    def testDownload(self):
        client = Client()

        # check download for experiment1 as tar
        response = client.get('/download/experiment/%i/tar/' %
                              self.experiment1.id)
        self.assertEqual(
            response['Content-Disposition'],
            'attachment; filename="%s-complete.tar"' %
            self.experiment1.title.replace(' ', '_'))
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(
            response.streaming_content,
            str(self.experiment1.title.replace(' ', '_')),
            reduce(lambda x, y: x + y, [
                ds.datafile_set.all()
                for ds in self.experiment1.datasets.all()
            ]))

        # check download of file1
        response = client.get('/download/datafile/%i/' % self.datafile1.id)

        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s"' % self.datafile1.filename)
        self.assertEqual(response.status_code, 200)
        response_content = ""
        for c in response.streaming_content:
            response_content += c
        self.assertEqual(response_content, 'Hello World!\n')

        # requesting file2 should be forbidden...
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 403)

        # check dataset1 download as tar
        response = client.post(
            '/download/datafiles/', {
                'expid': self.experiment1.id,
                'dataset': [self.dataset1.id],
                'datafile': [],
                'comptype': 'tar'
            })
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(response.streaming_content,
                             'Experiment 1-selection',
                             self.dataset1.datafile_set.all())

        # check dataset2 download
        response = client.post(
            '/download/datafiles/', {
                'expid': self.experiment2.id,
                'dataset': [self.dataset2.id],
                'datafile': []
            })
        self.assertEqual(response.status_code, 403)

        # check datafile1 download via POST
        response = client.post(
            '/download/datafiles/', {
                'expid': self.experiment1.id,
                'dataset': [],
                'datafile': [self.datafile1.id]
            })
        self.assertEqual(response.status_code, 200)
        self._check_tar_file(response.streaming_content,
                             'Experiment 1-selection', [self.datafile1])

        # check datafile2 download via POST
        response = client.post(
            '/download/datafiles/', {
                'expid': self.experiment2.id,
                'dataset': [],
                'datafile': [self.datafile2.id]
            })
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to "metadata only"
        self.experiment2.public_access = Experiment.PUBLIC_ACCESS_METADATA
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        # Metadata-only means "no file access"!
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to public
        self.experiment2.public_access = Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.datafile2.id)
        self.assertEqual(response.status_code, 200)
        # This should be a TIFF (which often starts with "II\x2a\x00")
        self.assertEqual(response['Content-Type'], 'image/tiff')
        response_content = ""
        for c in response.streaming_content:
            response_content += c
        self.assertEqual(response_content[0:4], "II\x2a\x00")

        # check experiment tar download with alternative organization
        response = client.get('/download/experiment/%i/tar/' %
                              self.experiment1.id)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response['Content-Disposition'],
            'attachment; filename="%s-complete.tar"' %
            self.experiment1.title.replace(' ', '_'))
        self._check_tar_file(response.streaming_content,
                             str(self.experiment1.id),
                             reduce(lambda x, y: x + y, [
                                 ds.datafile_set.all()
                                 for ds in self.experiment1.datasets.all()
                             ]),
                             simpleNames=True)

        # check experiment1 download with '.txt' filtered out (none left)
        response = client.get('/download/experiment/%i/tar/' %
                              self.experiment1.id)
        self.assertEqual(response.status_code, 200)

        # check experiment2 download with '.txt' filtered out
        response = client.get('/download/experiment/%i/tar/' %
                              self.experiment2.id)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response['Content-Disposition'],
            'attachment; filename="%s-complete.tar"' %
            self.experiment2.title.replace(' ', '_'))
        self._check_tar_file(response.streaming_content,
                             str(self.experiment2.id),
                             reduce(lambda x, y: x + y, [
                                 ds.datafile_set.all()
                                 for ds in self.experiment2.datasets.all()
                             ]),
                             simpleNames=True,
                             noTxt=True)

    def testDatasetFile(self):
        # check registered text file for physical file meta information
        df = DataFile.objects.get(pk=self.datafile1.id)  # skipping test # noqa # pylint: disable=W0101

        try:
            from magic import Magic
            self.assertEqual(df.mimetype, 'text/plain; charset=us-ascii')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(df.size, 13)
        self.assertEqual(df.md5sum, '8ddd8be4b179a529afa5f2ffae4b9858')

        # Now check we can calculate checksums and infer the mime type
        # for a JPG file.
        filename = 'tardis/tardis_portal/tests/test_data/ands-logo-hi-res.jpg'

        dataset = Dataset.objects.get(pk=self.dataset1.id)

        pdf1 = self._build_datafile(filename, basename(filename), dataset)
        self.assertEqual(pdf1.file_objects.get().verify(), True)
        pdf1 = DataFile.objects.get(pk=pdf1.pk)

        try:
            from magic import Magic  # noqa
            self.assertEqual(pdf1.mimetype, 'image/jpeg')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(pdf1.size, 14232)
        self.assertEqual(pdf1.md5sum, 'c450d5126ffe3d14643815204daf1bfb')

        # Now check that we can override the physical file meta information
        # We are setting size/checksums that don't match the actual file, so
        # the
        pdf2 = self._build_datafile(
            filename,
            filename,
            dataset,
            checksum=
            'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e',
            size=0,
            mimetype=
            'application/vnd.openxmlformats-officedocument.presentationml.presentation'
        )  # noqa
        self.assertEqual(pdf2.size, 0)
        self.assertEqual(pdf2.md5sum, '')
        self.assertEqual(pdf2.file_objects.get().verified, False)
        pdf2 = DataFile.objects.get(pk=pdf2.pk)
        try:
            from magic import Magic  # noqa
            self.assertEqual(
                pdf2.mimetype,
                'application/vnd.openxmlformats-officedocument.presentationml.presentation'
            )  # noqa
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(pdf2.size, 0)
        self.assertEqual(pdf2.md5sum, '')

        pdf2.mimetype = ''
        pdf2.save()
        pdf2.file_objects.get().save()
        pdf2 = DataFile.objects.get(pk=pdf2.pk)

        try:
            from magic import Magic  # noqa
            self.assertEqual(pdf2.mimetype, 'application/pdf')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
예제 #23
0
class DownloadTestCase(TestCase):

    def setUp(self):
        # create a test user
        self.user = User.objects.create_user(username='******',
                                             email='',
                                             password='******')

        # create a public experiment
        self.experiment1 = Experiment(title='Experiment 1',
                                      created_by=self.user,
                                      public_access=Experiment.PUBLIC_ACCESS_FULL)
        self.experiment1.save()

        # create a non-public experiment
        self.experiment2 = Experiment(title='Experiment 2',
                                      created_by=self.user,
                                      public_access=Experiment.PUBLIC_ACCESS_NONE)
        self.experiment2.save()

        # dataset1 belongs to experiment1
        self.dataset1 = Dataset()
        self.dataset1.save()
        self.dataset1.experiments.add(self.experiment1)
        self.dataset1.save()


        # dataset2 belongs to experiment2
        self.dataset2 = Dataset()
        self.dataset2.save()
        self.dataset2.experiments.add(self.experiment2)
        self.dataset2.save()

        # absolute path first
        filename1 = 'testfile.txt'
        filename2 = 'testfile.tiff'
        self.dest1 = abspath(join(settings.FILE_STORE_PATH, '%s/%s/'
                                  % (self.experiment1.id,
                                  self.dataset1.id)))
        self.dest2 = abspath(join(settings.FILE_STORE_PATH,
                                '%s/%s/'
                                  % (self.experiment2.id,
                                  self.dataset2.id)))
        if not exists(self.dest1):
            makedirs(self.dest1)
        if not exists(self.dest2):
            makedirs(self.dest2)

        testfile1 = abspath(join(self.dest1, filename1))
        f = open(testfile1, 'w')
        f.write("Hello World!\n")
        f.close()

        testfile2 = abspath(join(self.dest2, filename2))
        _generate_test_image(testfile2)

        size, sha512sum = get_size_and_sha512sum(testfile1)
        self.dataset_file1 = Dataset_File(dataset=self.dataset1,
                                          filename=filename1,
                                          protocol='',
                                          size=size,
                                          sha512sum=sha512sum,
                                          url='%d/%d/%s'
                                              % (self.experiment1.id,
                                                 self.dataset1.id,
                                                 filename1))
        self.dataset_file1.verify()
        self.dataset_file1.save()

        size, sha512sum = get_size_and_sha512sum(testfile2)
        self.dataset_file2 = Dataset_File(dataset=self.dataset2,
                                          filename=basename(filename2),
                                          protocol='',
                                          size=size,
                                          sha512sum=sha512sum,
                                          url='%d/%d/%s'
                                            % (self.experiment2.id,
                                               self.dataset2.id,
                                               filename2))
        self.dataset_file2.verify()
        self.dataset_file2.save()

    def tearDown(self):
        self.user.delete()
        self.experiment1.delete()
        self.experiment2.delete()
        rmtree(self.dest1)
        rmtree(self.dest2)

    def testView(self):
        client = Client()

        # check view of file1
        response = client.get('/datafile/view/%i/' % self.dataset_file1.id)

        self.assertEqual(response['Content-Disposition'],
                         'inline; filename="%s"'
                         % self.dataset_file1.filename)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Hello World!\n')

        # check view of file2
        response = client.get('/datafile/view/%i/' % self.dataset_file2.id)
        # Should be forbidden
        self.assertEqual(response.status_code, 403)

        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        # check view of file2 again
        response = client.get('/datafile/view/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 200)

        # The following behaviour relies on ImageMagick
        if IMAGEMAGICK_AVAILABLE:
            # file2 should have a ".png" filename
            self.assertEqual(response['Content-Disposition'],
                             'inline; filename="%s"'
                             % (self.dataset_file2.filename+'.png'))
            # file2 should be a PNG
            self.assertEqual(response['Content-Type'], 'image/png')
            png_signature = "\x89PNG\r\n\x1a\n"
            self.assertEqual(response.content[0:8], png_signature)
        else:
            # file2 should have a ".tiff" filename
            self.assertEqual(response['Content-Disposition'],
                             'inline; filename="%s"'
                             % (self.dataset_file2.filename))
            # file2 should be a TIFF
            self.assertEqual(response['Content-Type'], 'image/tiff')
            tiff_signature = "II\x2a\x00"
            self.assertEqual(response.content[0:4], tiff_signature)

    def _check_tar_file(self, content, rootdir, datafiles):
        # It should be a zip file
        with NamedTemporaryFile('w') as tempfile:
            tempfile.write(content)
            tempfile.flush()
            with open(tempfile.name, 'r') as zipread:
                # It should be a zip file (all of which start with "PK")
                expect(zipread.read(2)).to_equal('PK')
            expect(is_zipfile(tempfile.name)).to_be_truthy()
            with ZipFile(tempfile.name, 'r') as zf:
                expect(len(zf.namelist())).to_equal(len(datafiles))
                for df in datafiles:
                    filename = join(rootdir, str(df.dataset.id), df.filename)
                    expect(filename in zf.namelist()).to_be_truthy()

    def _check_zip_file(self, content, rootdir, datafiles):
        # It should be a zip file
        with NamedTemporaryFile('w') as tempfile:
            tempfile.write(content)
            tempfile.flush()
            with open(tempfile.name, 'r') as zipread:
                # It should be a zip file (all of which start with "PK")
                expect(zipread.read(2)).to_equal('PK')
            expect(is_zipfile(tempfile.name)).to_be_truthy()
            zf = ZipFile(tempfile.name, 'r')
            expect(len(zf.namelist())).to_equal(len(datafiles))
            for df in datafiles:
                filename = join(rootdir, str(df.dataset.id), df.filename)
                expect(filename in zf.namelist()).to_be_truthy()
            zf.close()


    def testDownload(self):
        client = Client()

        # check download for experiment1
        response = client.get('/download/experiment/%i/zip/' % self.experiment1.id)
        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="experiment%s-complete.zip"'
                         % self.experiment1.id)
        self.assertEqual(response.status_code, 200)
        self._check_zip_file(response.content, str(self.experiment1.id),
                             reduce(lambda x, y: x + y,
                                    [ds.dataset_file_set.all() \
                                     for ds in self.experiment1.datasets.all()]))

        # check download of file1
        response = client.get('/download/datafile/%i/' % self.dataset_file1.id)

        self.assertEqual(response['Content-Disposition'],
                         'attachment; filename="%s"'
                         % self.dataset_file1.filename)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Hello World!\n')

        # requesting file2 should be forbidden...
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 403)

        # check dataset1 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [self.dataset1.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 200)
        self._check_zip_file(response.content, 'datasets',
                             self.dataset1.dataset_file_set.all())

        # check dataset2 download
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [self.dataset2.id],
                                'datafile': []})
        self.assertEqual(response.status_code, 403)

        # check datafile1 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment1.id,
                                'dataset': [],
                                'datafile': [self.dataset_file1.id]})
        self.assertEqual(response.status_code, 200)
        self._check_zip_file(response.content, 'datasets', [self.dataset_file1])

        # check datafile2 download via POST
        response = client.post('/download/datafiles/',
                               {'expid': self.experiment2.id,
                                'dataset': [],
                                'datafile': [self.dataset_file2.id]})
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to "metadata only"
        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_METADATA
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        # Metadata-only means "no file access"!
        self.assertEqual(response.status_code, 403)

        # Check datafile2 download with second experiment to public
        self.experiment2.public_access=Experiment.PUBLIC_ACCESS_FULL
        self.experiment2.save()
        response = client.get('/download/datafile/%i/' % self.dataset_file2.id)
        self.assertEqual(response.status_code, 200)
        # This should be a TIFF (which often starts with "II\x2a\x00")
        self.assertEqual(response['Content-Type'], 'image/tiff')
        self.assertEqual(response.content[0:4], "II\x2a\x00")


    def testDatasetFile(self):

        # check registered text file for physical file meta information
        df = Dataset_File.objects.get(pk=self.dataset_file1.id)

        try:
            from magic import Magic
            self.assertEqual(df.mimetype, 'text/plain; charset=us-ascii')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(df.size, str(13))
        self.assertEqual(df.md5sum, '8ddd8be4b179a529afa5f2ffae4b9858')

        # now check a JPG file
        filename = abspath(join(dirname(__file__),
                                '../static/images/ands-logo-hi-res.jpg'))

        dataset = Dataset.objects.get(pk=self.dataset1.id)

        size, sha512sum = get_size_and_sha512sum(filename)
        pdf1 = Dataset_File(dataset=dataset,
                            filename=basename(filename),
                            size=str(size),
                            sha512sum=sha512sum,
                            url='file://%s' % filename,
                            protocol='file')
        pdf1.verify()
        pdf1.save()
        try:
            from magic import Magic
            self.assertEqual(pdf1.mimetype, 'image/jpeg')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(pdf1.size, str(14232))
        self.assertEqual(pdf1.md5sum, 'c450d5126ffe3d14643815204daf1bfb')

        # now check that we can override the physical file meta information
        pdf2 = Dataset_File(dataset=dataset,
                            filename=basename(filename),
                            url='file://%s' % filename,
                            protocol='file',
                            mimetype='application/vnd.openxmlformats-officedocument.presentationml.presentation',
                            size=str(0),
                            # Empty string always has the same hash
                            sha512sum='cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e')
        pdf2.save()
        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
        self.assertEqual(pdf2.size, str(0))
        self.assertEqual(pdf2.md5sum, '')

        pdf2.mimetype = ''
        pdf2.save()

        try:
            from magic import Magic
            self.assertEqual(pdf2.mimetype, 'application/pdf')
        except:
            # XXX Test disabled because lib magic can't be loaded
            pass
class ExperimentACLTestCase(TestCase):
    urls = 'tardis.urls'

    def setUp(self):

        # create a couple of test users
        self.user1 = User.objects.create_user('testuser1', '', 'secret')
        self.user2 = User.objects.create_user('testuser2', '', 'secret')
        self.user3 = User.objects.create_user('testuser3', '', 'secret')
        self.user4 = User.objects.create_user('testuser4', '', 'secret')

        # with standard permissions
        for user in [self.user1, self.user2, self.user3, self.user4]:
            user.user_permissions.add(Permission.objects.get(codename='add_experiment'))
            user.user_permissions.add(Permission.objects.get(codename='change_experiment'))
            user.user_permissions.add(Permission.objects.get(codename='change_group'))
            user.user_permissions.add(Permission.objects.get(codename='change_userauthentication'))
            user.user_permissions.add(Permission.objects.get(codename='change_experimentacl'))

        self.userProfile1 = UserProfile(user=self.user1)
        self.userProfile2 = UserProfile(user=self.user2)
        self.userProfile3 = UserProfile(user=self.user3)
        self.userProfile4 = UserProfile(user=self.user4)

        # each user will have their own client
        self.client1 = Client()
        self.client2 = Client()
        self.client3 = Client()
        self.client4 = Client()

        # user1 will own experiment1
        self.experiment1 = Experiment(
            title='Experiment1',
            institution_name='Australian Synchrotron',
            approved=True,
            public=False,
            created_by=self.user1,
            )
        self.experiment1.save()

        # user2 will own experiment2
        self.experiment2 = Experiment(
            title='Experiment2',
            institution_name='Australian Synchrotron',
            approved=True,
            public=False,
            created_by=self.user2,
            )
        self.experiment2.save()

        # experiment3 is public
        self.experiment3 = Experiment(
            title='Experiment3',
            institution_name='Australian Synchrotron',
            approved=True,
            public=True,
            created_by=self.user3,
            )
        self.experiment3.save()

        # experiment4 will be accessible based on location information
        self.experiment4 = Experiment(
            title='Experiment4',
            institution_name='Australian Synchrotron',
            approved=True,
            public=False,
            created_by=self.user1,
            )
        self.experiment4.save()

        # user1 owns experiment1
        acl = ExperimentACL(
            pluginId=django_user,
            entityId=str(self.user1.id),
            experiment=self.experiment1,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ExperimentACL.OWNER_OWNED,
            )
        acl.save()

        # user2 owns experiment2
        acl = ExperimentACL(
            pluginId=django_user,
            entityId=str(self.user2.id),
            experiment=self.experiment2,
            canRead=True,
            isOwner=True,
            aclOwnershipType=ExperimentACL.OWNER_OWNED,
            )
        acl.save()

        # experiment4 is accessible via location
        acl = ExperimentACL(
            pluginId='ip_address',
            entityId='127.0.0.1',
            experiment=self.experiment4,
            canRead=True,
            aclOwnershipType=ExperimentACL.SYSTEM_OWNED,
            )
        acl.save()

    def tearDown(self):
        self.client1.logout()
        self.client2.logout()
        self.client3.logout()
        self.client4.logout()

        self.experiment1.delete()
        self.experiment2.delete()
        self.experiment3.delete()
        self.experiment4.delete()

        self.user1.delete()
        self.user2.delete()
        self.user3.delete()
        self.user4.delete()

    def testReadAccess(self):
        login = self.client1.login(username=self.user1.username,
                                   password='******')
        self.assertTrue(login)

        # user1 should be see experiment1
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user1 should not be allowed to see experiment2
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # user1 should be allowed to see experiment3 as it's public
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user1 should be allowed to see experiment4 based on his IP address
        response = self.client1.get('/experiment/view/%i/'
                                   % (self.experiment4.id))
        self.assertEqual(response.status_code, 200)

        # create a group and add it to experiment1
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/group/%s/?canRead=true&create=true'
                                    % (self.experiment1.id, 'group1'))
        self.assertEqual(response.status_code, 200)

        # add user2 as admin to the newly created group
        group = Group.objects.get(name='group1')
        response = self.client1.get('/group/%i/add/%s/?isAdmin=true&authMethod=%s'
                                    % (group.id,
                                       self.user2.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # try it again
        response = self.client1.get('/group/%i/add/%s/?isAdmin=true&authMethod=%s'
                                    % (group.id,
                                       self.user2.username,
                                       localdb_auth_key))
        self.assertEqual(response.content, 'User %s is already member of that'
                         ' group.' % self.user2.username)
        self.assertEqual(response.status_code, 200)

        # user1 is not allowed to modify acls for experiment2
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s'
                                    % (self.experiment2.id,
                                       self.user1.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 403)

        # test add non-existent user
        non_existant = 'test_boozer'
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s'
                                    % (self.experiment1.id,
                                       non_existant,
                                       localdb_auth_key))

        self.assertContains(response, 'User %s does not exist' % non_existant)

        # test add to non existant experiment

        # Note: Ideally we'd like to check for error message, but we
        # can't hit it with the decorator in place.  However,
        # currently we check for a 403 (forbidden) error, as the
        # 'experiment_ownership_required' decorator simply checks if
        # the experiment_id appears in the specified user's ACL, and
        # assumes that the absence of the experiment_id means that the
        # experiment exists but the user doesn't have access to
        # it. This could possibly be changed to a 404 error.

        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s'
                                    % (9999, self.user1.username, localdb_auth_key))
        self.assertEqual(response.status_code, 403)

        self.client1.logout()

        # now check user2's permissions
        login = self.client2.login(username=self.user2.username,
                                   password='******')
        self.assertTrue(login)

        # user2 should be able to see experiment1 now
        response = self.client2.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be also able to see experiment2
        response = self.client2.get('/experiment/view/%i/'
                                   % (self.experiment2.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be allowed to see experiment3 as it's public
        response = self.client2.get('/experiment/view/%i/'
                                   % (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user2 should be able to add user3 to group1 (experiment1)
        response = self.client2.get('/group/%i/add/%s/?isAdmin=false&authMethod=%s'
                                   % (group.id, self.user3.username, localdb_auth_key))

        self.client2.logout()

        # now check user3's permissions
        login = self.client3.login(username=self.user3.username,
                                   password='******')
        self.assertTrue(login)

        # user3 should be able to see experiment1 via his group permissions
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # user3 should not be able to see experiment2
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # user3 should be able to see experiment3
        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment3.id))
        self.assertEqual(response.status_code, 200)

        # user3 should not be able to add another user4 to group1
        response = self.client3.get('/group/%i/add/%s/?isAdmin=false&authMethod=%s'
                                   % (group.id, 'testuser4', localdb_auth_key))
        self.assertEqual(response.status_code, 403)

        self.client3.logout()

        # ok, now do some tricky stuff
        today = datetime.datetime.today()
        yesterday = today - datetime.timedelta(days=1)
        tomorrow = today + datetime.timedelta(days=1)

        url = '/experiment/control_panel/%i/access_list/change/user/%s/'
        login = self.client1.login(username=self.user1.username,
                                   password='******')
        self.assertTrue(login)

        # remove user3 from group1
        response = self.client1.get('/group/%i/remove/%s/'
                                   % (group.id, self.user3.username))
        self.assertEqual(response.status_code, 200)

        # add user3 to experiment1
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s'
                                    % (self.experiment1.id,
                                       self.user3.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, '<div class="access_list_user">')

        # give user3 read permissions for experiment1 effictive TOMORROW
        response = self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'effectiveDate_year': tomorrow.year,
                           'effectiveDate_month': tomorrow.month,
                           'effectiveDate_day': tomorrow.day,
                           })
        self.assertEqual(response.status_code, 302)

        # check permissions for user3
        login = self.client3.login(username=self.user3.username,
                                   password='******')
        self.assertTrue(login)

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # change effictive date to TODAY
        response = self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'effectiveDate_year': today.year,
                           'effectiveDate_month': today.month,
                           'effectiveDate_day': today.day,
                           })
        self.assertEqual(response.status_code, 302)

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # change effictive date to YESTERDAY
        self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'effectiveDate_year': yesterday.year,
                           'effectiveDate_month': yesterday.month,
                           'effectiveDate_day': yesterday.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to TOMORROW
        self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'expiryDate_year': tomorrow.year,
                           'expiryDate_month': tomorrow.month,
                           'expiryDate_day': tomorrow.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to TODAY
        self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'expiryDate_year': today.year,
                           'expiryDate_month': today.month,
                           'expiryDate_day': today.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # set expiry date to YESTERDAY
        self.client1.post(url % (self.experiment1.id, self.user3.username),
                          {'canRead': True,
                           'expiryDate_year': yesterday.year,
                           'expiryDate_month': yesterday.month,
                           'expiryDate_day': yesterday.day,
                           })

        response = self.client3.get('/experiment/view/%i/'
                                   % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # remove user3 from experiment1 again
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/'
                                    % (self.experiment1.id, self.user3.username))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'OK')

        # try again, see if it falls over
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/'
                                    % (self.experiment1.id, self.user3.username))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content,
                         'The user %s does not have access to this experiment.'
                         % self.user3.username)

        # try to remove from a non-existant experiment
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/'
                                    % (9999, self.user3.username))
        self.assertEqual(response.status_code, 403)

        # try to remove the owner
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/remove/user/%s/'
                                    % (self.experiment1.id, self.user1.username))
        self.assertEqual(response.content,
                         'Cannot remove your own user access.')

        self.client1.logout()
        self.client3.logout()

    def testWriteAccess(self):
        # without logging in the request should be redirected
        response = self.client1.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 302)

        # now check access for user1
        login = self.client1.login(username=self.user1.username,
                                   password='******')
        self.assertTrue(login)
        response = self.client1.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # write access has not been granted for experiment2
        response = self.client1.get('/experiment/edit/%i/' % (self.experiment2.id))
        self.assertEqual(response.status_code, 403)

        # neither experiment3 which is public
        response = self.client1.get('/experiment/edit/%i/' % (self.experiment3.id))
        self.assertEqual(response.status_code, 403)

        # create a group 'group1w' with write permissions
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/group/%s/?canRead=true&canWrite=true&create=true'
                                    % (self.experiment1.id, 'group1w'))
        self.assertEqual(response.status_code, 200)

        # add user2 to 'group1w' which gives him write permissions
        group = Group.objects.get(name='group1w')
        response = self.client1.get('/group/%i/add/%s/?isAdmin=false&authMethod=%s'
                                   % (group.id, self.user2.username, localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # add user3 explicitly to experiment1
        response = self.client1.get('/experiment/control_panel/%i/access_list'
                                    '/add/user/%s/?authMethod=%s&canRead=true'
                                    '&canWrite=true'
                                    % (self.experiment1.id,
                                       self.user3.username,
                                       localdb_auth_key))
        self.assertEqual(response.status_code, 200)

        # check newly created permissions for user2 and user3
        response = self.client2.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 302)

        response = self.client3.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 302)

        login = self.client2.login(username=self.user2.username, password='******')
        self.assertTrue(login)

        login = self.client3.login(username=self.user3.username, password='******')
        self.assertTrue(login)

        response = self.client2.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        response = self.client3.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # now the fancy stuff with timestamps
        today = datetime.datetime.today()
        yesterday = today - datetime.timedelta(days=1)
        tomorrow = today + datetime.timedelta(days=1)

        url = '/experiment/control_panel/%i/access_list/change/group/%i/'

        # give group 'group1w' write permissions for experiment1 effictive TOMORROW
        response = self.client1.post(url % (self.experiment1.id, group.id),
                                     {'canRead': True,
                                      'canWrite': True,
                                      'effectiveDate_year': tomorrow.year,
                                      'effectiveDate_month': tomorrow.month,
                                      'effectiveDate_day': tomorrow.day,
                                      })

        self.assertEqual(response.status_code, 302)

        response = self.client2.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # change effictive date to TODAY
        response = self.client1.post(url % (self.experiment1.id, group.id),
                          {'canRead': True,
                           'canWrite': True,
                           'effectiveDate_year': today.year,
                           'effectiveDate_month': today.month,
                           'effectiveDate_day': today.day,
                           })
        self.assertEqual(response.status_code, 302)

        # now user2 should have write access again
        response = self.client2.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        # repeat all the tests with timestamps for user3
        url = '/experiment/control_panel/%i/access_list/change/user/%s/'

        # give user3 write permissions for experiment1 effictive TOMORROW
        response = self.client1.post(url % (self.experiment1.id, self.user3.username),
                                     {'canRead': True,
                                      'canWrite': True,
                                      'effectiveDate_year': tomorrow.year,
                                      'effectiveDate_month': tomorrow.month,
                                      'effectiveDate_day': tomorrow.day,
                                      })
        self.assertEqual(response.status_code, 302)

        response = self.client3.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 403)

        # change effictive date to TODAY
        response = self.client1.post(url % (self.experiment1.id, self.user3.username),
                                     {'canRead': True,
                                      'canWrite': True,
                                      'effectiveDate_year': today.year,
                                      'effectiveDate_month': today.month,
                                      'effectiveDate_day': today.day,
                                      })
        self.assertEqual(response.status_code, 302)

        # now user3 should have write access again
        response = self.client3.get('/experiment/edit/%i/' % (self.experiment1.id))
        self.assertEqual(response.status_code, 200)

        self.client1.logout()
        self.client2.logout()
        self.client3.logout()

    def testCantEditPublicExperiment(self):
        login = self.client3.login(username=self.user3.username, password='******')
        self.assertTrue(login)

        # user3 has acl to write to experiment3
        acl = ExperimentACL(
            pluginId=django_user,
            entityId=str(self.user3.id),
            experiment=self.experiment3,
            canRead=True,
            canWrite=True,
            aclOwnershipType=ExperimentACL.OWNER_OWNED,
            )
        acl.save()

        response = self.client3.get('/experiment/edit/%i/' % (self.experiment3.id))
        self.assertEqual(response.status_code, 403)

        response = self.client3.post('/experiment/edit/%i/' % (self.experiment3.id),
                                     {'anything': True, })
        self.assertEqual(response.status_code, 403)

        acl.delete()
        self.client3.logout()

    def testOwnedExperiments(self):
        user = AnonymousUser()
        # not logged in
        class MockRequest:
            pass
        request = MockRequest()
        request.user = user
        num_exps = Experiment.safe.owned(request).count()
        self.assertEqual(num_exps, 0)
예제 #25
0
class ParameterSetManagerTestCase(TestCase):
    def setUp(self):
        from django.contrib.auth.models import User
        from tempfile import mkdtemp

        user = '******'
        pwd = 'secret'
        email = ''
        self.user = User.objects.create_user(user, email, pwd)

        self.test_dir = mkdtemp()

        self.exp = Experiment(title='test exp1',
                              institution_name='monash',
                              created_by=self.user)
        self.exp.save()

        self.dataset = Dataset(description="dataset description...")
        self.dataset.save()
        self.dataset.experiments.add(self.exp)
        self.dataset.save()

        self.datafile = DataFile(dataset=self.dataset,
                                 filename="testfile.txt",
                                 size="42",
                                 md5sum='bogus')
        self.datafile.save()

        self.dfo = DataFileObject(
            datafile=self.datafile,
            storage_box=self.datafile.get_default_storage_box(),
            uri="1/testfile.txt")
        self.dfo.save()

        self.schema = Schema(namespace="http://localhost/psmtest/df/",
                             name="Parameter Set Manager",
                             type=3)
        self.schema.save()

        self.parametername1 = ParameterName(schema=self.schema,
                                            name="parameter1",
                                            full_name="Parameter 1")
        self.parametername1.save()

        self.parametername2 = ParameterName(schema=self.schema,
                                            name="parameter2",
                                            full_name="Parameter 2",
                                            data_type=ParameterName.NUMERIC)
        self.parametername2.save()

        self.parametername3 = ParameterName(schema=self.schema,
                                            name="parameter3",
                                            full_name="Parameter 3",
                                            data_type=ParameterName.DATETIME)
        self.parametername3.save()

        self.datafileparameterset = DatafileParameterSet(
            schema=self.schema, datafile=self.datafile)
        self.datafileparameterset.save()

        self.datafileparameter1 = DatafileParameter(
            parameterset=self.datafileparameterset,
            name=self.parametername1,
            string_value="test1")
        self.datafileparameter1.save()

        self.datafileparameter2 = DatafileParameter(
            parameterset=self.datafileparameterset,
            name=self.parametername2,
            numerical_value=2)
        self.datafileparameter2.save()

        # Create a ParameterName and Parameter of type LINK to an experiment
        self.parametername_exp_link = ParameterName(
            schema=self.schema,
            name="exp_link",
            full_name="This parameter is a experiment LINK",
            data_type=ParameterName.LINK)
        self.parametername_exp_link.save()

        self.exp_link_param = DatafileParameter(
            parameterset=self.datafileparameterset,
            name=self.parametername_exp_link)
        exp_url = self.exp.get_absolute_url()  # /experiment/view/1/
        self.exp_link_param.set_value(exp_url)
        self.exp_link_param.save()

        # Create a ParameterName and Parameter of type LINK to a dataset
        self.parametername_dataset_link = ParameterName(
            schema=self.schema,
            name="dataset_link",
            full_name="This parameter is a dataset LINK",
            data_type=ParameterName.LINK)
        self.parametername_dataset_link.save()

        self.dataset_link_param = DatafileParameter(
            parameterset=self.datafileparameterset,
            name=self.parametername_dataset_link)
        dataset_url = self.dataset.get_absolute_url()  # /dataset/1/
        self.dataset_link_param.set_value(dataset_url)
        self.dataset_link_param.save()

        # Create a ParameterName type LINK to an unresolvable (non-URL)
        # free-text value
        self.parametername_unresolvable_link = ParameterName(
            schema=self.schema,
            name="freetext_link",
            full_name="This parameter is a non-URL LINK",
            data_type=ParameterName.LINK)
        self.parametername_unresolvable_link.save()

    def tearDown(self):
        self.exp.delete()
        self.user.delete()
        self.parametername1.delete()
        self.parametername2.delete()
        self.parametername3.delete()
        self.parametername_exp_link.delete()
        self.parametername_dataset_link.delete()
        self.parametername_unresolvable_link.delete()
        self.schema.delete()

    def test_existing_parameterset(self):

        psm = ParameterSetManager(parameterset=self.datafileparameterset)

        self.assertTrue(
            psm.get_schema().namespace == "http://localhost/psmtest/df/")

        self.assertTrue(psm.get_param("parameter1").string_value == "test1")

        self.assertTrue(psm.get_param("parameter2", True) == 2)

    def test_new_parameterset(self):

        psm = ParameterSetManager(parentObject=self.datafile,
                                  schema="http://localhost/psmtest/df2/")

        self.assertTrue(
            psm.get_schema().namespace == "http://localhost/psmtest/df2/")

        psm.set_param("newparam1", "test3", "New Parameter 1")

        self.assertTrue(psm.get_param("newparam1").string_value == "test3")

        self.assertTrue(
            psm.get_param("newparam1").name.full_name == "New Parameter 1")

        psm.new_param("newparam1", "test4")

        self.assertTrue(len(psm.get_params("newparam1", True)) == 2)

        psm.set_param_list("newparam2", ("a", "b", "c", "d"))

        self.assertTrue(len(psm.get_params("newparam2")) == 4)

        psm.set_params_from_dict({"newparam2": "test5", "newparam3": 3})

        self.assertTrue(psm.get_param("newparam2", True) == "test5")

        # the newparam3 gets created and '3' is set to a string_value
        # since once cannot assume that an initial numeric value
        # will imply continuing numeric type for this new param
        self.assertTrue(psm.get_param("newparam3").string_value == '3')

        psm.delete_params("newparam1")

        self.assertTrue(len(psm.get_params("newparam1", True)) == 0)

    def test_link_parameter_type(self):
        """
        Test that Parameter.link_gfk (GenericForeignKey) is correctly
        assigned after using Parameter.set_value(some_url) for a LINK Parameter.
        """
        psm = ParameterSetManager(parameterset=self.datafileparameterset)

        # Check link to experiment
        exp_url = self.exp.get_absolute_url()  # /experiment/view/1/
        self.assertTrue(psm.get_param("exp_link").string_value == exp_url)

        self.assertTrue(psm.get_param("exp_link").link_id == self.exp.id)

        exp_ct = ContentType.objects.get(model__iexact="experiment")
        self.assertTrue(psm.get_param("exp_link").link_ct == exp_ct)

        self.assertTrue(psm.get_param("exp_link").link_gfk == self.exp)

        # Check link to dataset
        dataset_url = self.dataset.get_absolute_url()  # /dataset/1/
        self.assertTrue(
            psm.get_param("dataset_link").string_value == dataset_url)

        self.assertTrue(
            psm.get_param("dataset_link").link_id == self.dataset.id)

        dataset_ct = ContentType.objects.get(model__iexact="dataset")
        self.assertTrue(psm.get_param("dataset_link").link_ct == dataset_ct)

        self.assertTrue(psm.get_param("dataset_link").link_gfk == self.dataset)

    def test_link_parameter_type_extra(self):
        # make a second ParameterSet for testing some variations
        # in URL values
        self.datafileparameterset2 = DatafileParameterSet(
            schema=self.schema, datafile=self.datafile)
        self.datafileparameterset2.save()

        psm = ParameterSetManager(parameterset=self.datafileparameterset2)

        self.dataset_link_param2 = DatafileParameter(
            parameterset=self.datafileparameterset2,
            name=self.parametername_dataset_link)
        # /dataset/1 - no trailing slash
        dataset_url = self.dataset.get_absolute_url()
        self.dataset_link_param2.set_value(dataset_url)
        self.dataset_link_param2.save()

        # Check link_id/link_ct/link_gfk to dataset
        self.assertTrue(
            psm.get_param("dataset_link").link_id == self.dataset.id)

        dataset_ct = ContentType.objects.get(model__iexact="dataset")
        self.assertTrue(psm.get_param("dataset_link").link_ct == dataset_ct)

        self.assertTrue(psm.get_param("dataset_link").link_gfk == self.dataset)

        # Test links of the form /api/v1/experiment/<experiment_id>/
        self.exp_link_param2 = DatafileParameter(
            parameterset=self.datafileparameterset2,
            name=self.parametername_exp_link)
        exp_url = '/api/v1/experiment/%s/' % self.exp.id
        self.exp_link_param2.set_value(exp_url)
        self.exp_link_param2.save()

        # Check link_id/link_ct/link_gfk to experiment
        self.assertTrue(psm.get_param("exp_link").link_id == self.exp.id)

        exp_ct = ContentType.objects.get(model__iexact="experiment")
        self.assertTrue(psm.get_param("exp_link").link_ct == exp_ct)

        self.assertTrue(psm.get_param("exp_link").link_gfk == self.exp)

    def test_unresolvable_link_parameter(self):
        """
        Test that LINK Parameters that can't be resolved to a model (including
        non-URL values) still work.
        """
        self.datafileparameterset3 = DatafileParameterSet(
            schema=self.schema, datafile=self.datafile)
        self.datafileparameterset3.save()

        psm = ParameterSetManager(parameterset=self.datafileparameterset3)

        # Create a Parameter of type LINK to an unresolvable (non-URL)
        # free-text value
        self.freetext_link_param = DatafileParameter(
            parameterset=self.datafileparameterset3,
            name=self.parametername_unresolvable_link)
        self.assertRaises(
            SuspiciousOperation,
            lambda: self.freetext_link_param.set_value("FREETEXT_ID_123"))

    def test_tz_naive_date_handling(self):
        """
        Ensure that dates are handling in a timezone-aware way.
        """
        psm = ParameterSetManager(parameterset=self.datafileparameterset)

        psm.new_param("parameter3", str(datetime(1970, 01, 01, 10, 0, 0)))

        expect(psm.get_param("parameter3", True))\
            .to_equal(datetime(1970, 01, 01, 0, 0, 0, tzinfo=pytz.utc))

    def test_tz_aware_date_handling(self):
        """
        Ensure that dates are handling in a timezone-aware way.
        """
        psm = ParameterSetManager(parameterset=self.datafileparameterset)

        psm.new_param("parameter3", '1970-01-01T08:00:00+08:00')

        expect(psm.get_param("parameter3", True))\
            .to_equal(datetime(1970, 01, 01, 0, 0, 0, tzinfo=pytz.utc))