def to_file_dict(self): """Returns a dictionary correctly formatted as a data api response. This method first constructs a dictionary that looks like a response from an agave call to `files.listing`. After this it instantiates a :class:`~designsafe.apps.api.agave.files.AgaveFile` object and returns the result of :meth:`~designsafe.apps.api.agave.files.AgaveFile.to_dict`. We hand off the dict construction to the :class:`~designsafe.apps.api.agave.files.AgaveFile` class so we don't have to implement it twice. :param string pems_user: User to filter permissions for :returns: dict object representation of a file :rtype: dict .. note:: in future releases the ES documents in the index should look like the response of an agave call to `files.listing`. We would need to keep this method to hand of the dict construction to the :class:`~designsafe.apps.api.agave.files.AgaveFile` class """ try: lm = dateutil.parser.parse(self.lastModified) except AttributeError: lm = datetime.datetime.now() pems = self.to_dict()['permissions'] wrap = { 'format': getattr(self, 'format', 'folder'), 'lastModified': lm, 'length': self.length, 'mimeType': self.mimeType, 'name': self.name, 'path': os.path.join(self.path, self.name).strip('/'), 'permissions': pems, 'system': self.systemId, 'type': self.type, '_pems': pems } f = AgaveFile(wrap = wrap) extra = { 'meta': { 'keywords': self.to_dict().get('keywords', list([])), 'systemTags': self.to_dict().get('systemTags', list([])) } } return f.to_dict(extra = extra)
def to_file_dict(self): """Returns a dictionary correctly formatted as a data api response. This method first constructs a dictionary that looks like a response from an agave call to `files.listing`. After this it instantiates a :class:`~designsafe.apps.api.agave.files.AgaveFile` object and returns the result of :meth:`~designsafe.apps.api.agave.files.AgaveFile.to_dict`. We hand off the dict construction to the :class:`~designsafe.apps.api.agave.files.AgaveFile` class so we don't have to implement it twice. :param string pems_user: User to filter permissions for :returns: dict object representation of a file :rtype: dict .. note:: in future releases the ES documents in the index should look like the response of an agave call to `files.listing`. We would need to keep this method to hand of the dict construction to the :class:`~designsafe.apps.api.agave.files.AgaveFile` class """ try: lm = dateutil.parser.parse(self.lastModified) except AttributeError: lm = datetime.datetime.now() pems = self.to_dict()['permissions'] wrap = { 'format': getattr(self, 'format', 'folder'), 'lastModified': lm, 'length': self.length, 'mimeType': self.mimeType, 'name': self.name, 'path': os.path.join(self.path, self.name).strip('/'), 'permissions': pems, 'system': self.systemId, 'type': self.type, '_pems': pems } f = AgaveFile(wrap=wrap) extra = { 'meta': { 'keywords': self.to_dict().get('keywords', list([])), 'systemTags': self.to_dict().get('systemTags', list([])) } } return f.to_dict(extra=extra)
def preview(self, file_id, **kwargs): system, file_path = self.parse_file_id(file_id) f = AgaveFile.from_file_path(system, None, file_path, agave_client=self.agave_client, source="public") if f.previewable: fmt = kwargs.get("format", "json") if fmt == "html": context = {} ext = f.ext.lower() if ext in AgaveFile.SUPPORTED_IMAGE_PREVIEW_EXTS: postit = f.create_postit(force=False, lifetime=360) context["image_preview"] = postit["_links"]["self"]["href"] elif ext in AgaveFile.SUPPORTED_TEXT_PREVIEW_EXTS: content = f.download() context["text_preview"] = content elif ext in AgaveFile.SUPPORTED_OBJECT_PREVIEW_EXTS: postit = f.create_postit(force=False) context["object_preview"] = postit["_links"]["self"]["href"] return "designsafe/apps/api/data/agave/preview.html", context else: preview_url = ( reverse("designsafe_api:file", args=[self.resource, file_id]) + "?action=preview&format=html" ) return {"href": preview_url} else: return None
def test_file__init__(self): ac = mock.Mock(spec=Agave) af = AgaveFile(wrap=self.afile_json, agave_client=ac) self.assertEqual(af.agave_client, ac) self.assertDictEqual(af._wrap, self.afile_json) self.assertFalse(af._permissions)
def preview(self, file_id, **kwargs): system, file_path = self.parse_file_id(file_id) f = AgaveFile.from_file_path(system, None, file_path, agave_client=self.agave_client, source='public') if f.previewable: fmt = kwargs.get('format', 'json') if fmt == 'html': context = {} ext = f.ext.lower() if ext in AgaveFile.SUPPORTED_IMAGE_PREVIEW_EXTS: postit = f.create_postit(force=False, lifetime=360) context['image_preview'] = postit['_links']['self']['href'] elif ext in AgaveFile.SUPPORTED_TEXT_PREVIEW_EXTS: content = f.download() context['text_preview'] = content elif ext in AgaveFile.SUPPORTED_OBJECT_PREVIEW_EXTS: postit = f.create_postit(force=False) context['object_preview'] = postit['_links']['self'][ 'href'] return 'designsafe/apps/api/data/agave/preview.html', context else: preview_url = reverse('designsafe_api:file', args=[self.resource, file_id ]) + '?action=preview&format=html' return {'href': preview_url} else: return None
def _agave_listing(self, system, file_path, **kwargs): """Returns a "listing" dict constructed with the response from Agave. :param str sytem: System id :param str file_path: Path to list :returns: A dict with information of the listed file and, when possible, a list of :class:`~designsafe.apps.api.data.agave.files.AgaveFile` objects dict in the key ``children`` :rtype: dict Notes: ----- This should not be called directly. See py:meth:`listing(file_id)` for more information. """ listing = AgaveFile.listing(system, file_path, self.agave_client, source="public", **kwargs) root_file = filter(lambda x: x.full_path == file_path, listing) default_pems = [ { "username": self.username, "permission": {"read": True, "write": False, "execute": True}, "recursive": True, } ] list_data = root_file[0].to_dict(default_pems=default_pems) list_data["children"] = [o.to_dict(default_pems=default_pems) for o in listing if o.full_path != file_path] return list_data
def test_folder__init__(self): ac = mock.Mock(spec=Agave) af = AgaveFile(wrap=self.afile_json, agave_client=ac) self.assertEqual(af.agave_client, ac) self.assertDictEqual(af._wrap, self.afile_json) self.assertEqual(af.name, af.path.split('/')[-1]) self.assertFalse(af._permissions)
def test_folder__init__with_pems(self): ac = mock.Mock(spec=Agave) self.afile_json['permissions'] = self.apems_json af = AgaveFile(wrap=self.afile_json, agave_client=ac) self.assertEqual(af.agave_client, ac) self.assertDictEqual(af._wrap, self.afile_json) self.assertEqual(af.name, af.path.split('/')[-1]) for i, pem in enumerate(af.permissions): self.assertDictEqual(pem, self.apems_json[i])
def test_from_file_path(self): ac = mock.Mock(autospec = Agave) ac.files.list.return_value = [self.afile_json] file_path = '%s/%s' % (self.user.username, self.afile_json['path']) af = AgaveFile.from_file_path(settings.AGAVE_STORAGE_SYSTEM, self.user.username, file_path, agave_client = ac) ac.files.list.assert_called_with(systemId= settings.AGAVE_STORAGE_SYSTEM, filePath = file_path) self.assertEqual(af.full_path, self.afile_json['path'])
def test_mkdir(self, mock_from_file_path): ac = mock.Mock(autospec = Agave) ac.files.manage.return_value = self.afile_json tail, head = os.path.split(self.afile_json['path']) file_path = self.afile_json['path'] af = AgaveFile.mkdir(settings.AGAVE_STORAGE_SYSTEM, self.user.username, tail, head, agave_client = ac) body = '{{"action": "mkdir", "path": "{}"}}'.format(head) ac.files.manage.assert_called_with(systemId= settings.AGAVE_STORAGE_SYSTEM, filePath = tail, body = body) mock_from_file_path.assert_called_with(settings.AGAVE_STORAGE_SYSTEM, self.user.username, file_path, ac)
def test_from_file_path(self): ac = mock.Mock(autospec=Agave) ac.files.list.return_value = [self.afile_json] file_path = '%s/%s' % (self.user.username, self.afile_json['path']) af = AgaveFile.from_file_path(settings.AGAVE_STORAGE_SYSTEM, self.user.username, file_path, agave_client=ac) ac.files.list.assert_called_with( systemId=settings.AGAVE_STORAGE_SYSTEM, filePath=file_path) self.assertEqual(af.full_path, self.afile_json['path'])
def test_listing(self): with open('designsafe/apps/api/fixtures/agave_home_listing.json') as f: listing_json = json.load(f) ac = mock.Mock(autospec = Agave) ac.files.list.return_value = listing_json file_path = '%s/%s' % (self.user.username, self.afile_json['path']) listing = AgaveFile.listing(settings.AGAVE_STORAGE_SYSTEM, file_path, agave_client = ac) ac.files.list.assert_called_with(systemId = settings.AGAVE_STORAGE_SYSTEM, filePath = file_path, limit = 100, offset = 0) for i, af in enumerate(listing): self.assertEqual(af.full_path, listing_json[i]['path'])
def test_mkdir(self, mock_from_file_path): ac = mock.Mock(autospec=Agave) ac.files.manage.return_value = self.afile_json tail, head = os.path.split(self.afile_json['path']) file_path = self.afile_json['path'] af = AgaveFile.mkdir(settings.AGAVE_STORAGE_SYSTEM, self.user.username, tail, head, agave_client=ac) body = '{{"action": "mkdir", "path": "{}"}}'.format(head) ac.files.manage.assert_called_with( systemId=settings.AGAVE_STORAGE_SYSTEM, filePath=tail, body=body) mock_from_file_path.assert_called_with(settings.AGAVE_STORAGE_SYSTEM, self.user.username, file_path, ac)
def test_listing(self): with open('designsafe/apps/api/fixtures/agave_home_listing.json') as f: listing_json = json.load(f) ac = mock.Mock(autospec=Agave) ac.files.list.return_value = listing_json file_path = '%s/%s' % (self.user.username, self.afile_json['path']) listing = AgaveFile.listing(settings.AGAVE_STORAGE_SYSTEM, file_path, agave_client=ac) ac.files.list.assert_called_with( systemId=settings.AGAVE_STORAGE_SYSTEM, filePath=file_path, limit=100, offset=0) for i, af in enumerate(listing): self.assertEqual(af.full_path, listing_json[i]['path'])
def download(self, file_id, **kwargs): """Get the download link for a file :param str file_id: String with the format <filesystem id>[/ | /<username> [/ | /<file_path>] ] :returns: a dict with a single key `href` which has the direct noauth link to download a file :rtype: dict """ system, file_path = self.parse_file_id(file_id) f = AgaveFile.from_file_path(system, None, file_path, agave_client=self.agave_client, source="public") if f.type == "file": postit = f.create_postit(force=True, max_uses=10, lifetime=3600) return {"href": postit["_links"]["self"]["href"]} else: return None
def _agave_listing(self, system, file_path, **kwargs): """Returns a "listing" dict constructed with the response from Agave. :param str sytem: System id :param str file_path: Path to list :returns: A dict with information of the listed file and, when possible, a list of :class:`~designsafe.apps.api.data.agave.files.AgaveFile` objects dict in the key ``children`` :rtype: dict Notes: ----- This should not be called directly. See py:meth:`listing(file_id)` for more information. """ listing = AgaveFile.listing(system, file_path, self.agave_client, source='public', **kwargs) root_file = filter(lambda x: x.full_path == file_path, listing) default_pems = [{ 'username': self.username, 'permission': { 'read': True, 'write': False, 'execute': True }, 'recursive': True }] list_data = root_file[0].to_dict(default_pems=default_pems) list_data['children'] = [ o.to_dict(default_pems=default_pems) for o in listing if o.full_path != file_path ] return list_data
def download(self, file_id, **kwargs): """Get the download link for a file :param str file_id: String with the format <filesystem id>[/ | /<username> [/ | /<file_path>] ] :returns: a dict with a single key `href` which has the direct noauth link to download a file :rtype: dict """ system, file_path = self.parse_file_id(file_id) f = AgaveFile.from_file_path(system, None, file_path, agave_client=self.agave_client, source='public') if f.type == 'file': postit = f.create_postit(force=True, max_uses=10, lifetime=3600) return {'href': postit['_links']['self']['href']} else: return None
def get_mock_agave_file(self): ac = mock.Mock() wrap = self.afile_json.copy() wrap['lastModified'] = dateutil.parser.parse(wrap['lastModified']) af = AgaveFile(wrap = wrap, agave_client = ac) return af
def share_agave(self, username, file_id, permissions, recursive): try: n = Notification(event_type = 'data', status = 'INFO', operation = 'share_initializing', message = 'File sharing is initializing. Please wait...', user = username, extra = {'target_path': reverse('designsafe_data:data_browser', args=['agave', file_id])}) n.save() user = get_user_model().objects.get(username=username) from designsafe.apps.api.data import AgaveFileManager from designsafe.apps.api.data.agave.file import AgaveFile from designsafe.apps.api.data.agave.elasticsearch.documents import Object agave_fm = AgaveFileManager(user) system_id, file_user, file_path = agave_fm.parse_file_id(file_id) f = AgaveFile.from_file_path(system_id, username, file_path, agave_client=agave_fm.agave_client) f.share(permissions, recursive) #reindex_agave.apply_async(args=(self.username, file_id)) # self.indexer.index(system, file_path, file_user, pems_indexing=True) esf = Object.from_file_path(system_id, username, file_path) esf.share(username, permissions, recursive) # Notify owner share completed n = Notification(event_type = 'data', status = 'SUCCESS', operation = 'share_finished', message = 'File permissions were updated successfully.', user = username, extra = {'target_path': reverse('designsafe_data:data_browser', args=['agave', file_id])}) n.save() # Notify users they have new shared files for pem in permissions: if pem['permission'] != 'NONE': message = '%s shared some files with you.' % user.get_full_name() n = Notification(event_type = 'data', status = 'SUCCESS', operation = 'share_finished', message = message, user = pem['user_to_share'], extra = {'target_path': reverse('designsafe_data:data_browser', args=['agave', file_id])}) n.save() except: logger.error('Error sharing file/folder', exc_info=True, extra = { 'username': username, 'file_id': file_id, 'permissions': permissions }) n = Notification(event_type='data', status=Notification.ERROR, operation='share_error', message='We were unable to share the specified folder/file(s). ' 'Please try again...', user=username, extra={}) n.save()
def share_agave(self, username, file_id, permissions, recursive): try: # n = Notification(event_type = 'data', # status = 'INFO', # operation = 'share_initializing', # message = 'File sharing is initializing. Please wait...', # user = username, # extra = {'target_path': reverse('designsafe_data:data_depot', # args=['agave', file_id])}) # n.save() user = get_user_model().objects.get(username=username) from designsafe.apps.api.data import AgaveFileManager from designsafe.apps.api.data.agave.file import AgaveFile from designsafe.apps.api.data.agave.elasticsearch.documents import Object agave_fm = AgaveFileManager(user) system_id, file_user, file_path = agave_fm.parse_file_id(file_id) f = AgaveFile.from_file_path(system_id, username, file_path, agave_client=agave_fm.agave_client) f_dict = f.to_dict() n = Notification(event_type = 'data', status = 'INFO', operation = 'share_initializing', message = 'File sharing is initializing. Please wait...', user = username, extra = f_dict) n.save() f.share(permissions, recursive) #reindex_agave.apply_async(args=(self.username, file_id)) # self.indexer.index(system, file_path, file_user, pems_indexing=True) esf = Object.from_file_path(system_id, username, file_path) esf.share(username, permissions, recursive) # Notify owner share completed n = Notification(event_type = 'data', status = 'SUCCESS', operation = 'share_finished', message = 'File permissions were updated successfully.', user = username, extra = f_dict) n.save() # Notify users they have new shared files for pem in permissions: if pem['permission'] != 'NONE': message = '%s shared some files with you.' % user.get_full_name() n = Notification(event_type = 'data', status = 'SUCCESS', operation = 'share_finished', message = message, user = pem['user_to_share'], extra = f_dict) n.save() except: logger.error('Error sharing file/folder', exc_info=True, extra = { 'username': username, 'file_id': file_id, 'permissions': permissions }) n = Notification(event_type='data', status=Notification.ERROR, operation='share_error', message='We were unable to share the specified folder/file(s). ' 'Please try again...', user=username, extra={'system': system_id, 'path': file_path }) n.save()
def get_mock_file(self): ac = mock.Mock() af = AgaveFile(wrap=self.afile_json.copy(), agave_client=ac) return af