def clone(self, new_event, options): if 'attachments' not in options: return folder_mapping = {} attrs = get_simple_column_attrs(AttachmentFolder) for old_folder in self.find_folders(): new_folder = AttachmentFolder(event_id=new_event.id, **{attr: getattr(old_folder, attr) for attr in attrs}) if new_folder.linked_object is None: continue new_folder.acl = old_folder.acl db.session.add(new_folder) folder_mapping[old_folder] = new_folder attrs = get_simple_column_attrs(Attachment) - {'modified_dt'} for old_attachment in self.find_attachments(): folder = folder_mapping.get(old_attachment.folder) if not folder: continue new_attachment = Attachment(folder=folder, user_id=old_attachment.user_id, acl=old_attachment.acl, **{attr: getattr(old_attachment, attr) for attr in attrs}) if new_attachment.type == AttachmentType.file: old_file = old_attachment.file new_attachment.file = AttachmentFile( attachment=new_attachment, user_id=old_file.user_id, filename=old_file.filename, content_type=old_file.content_type ) with old_file.open() as fd: new_attachment.file.save(fd) db.session.add(new_attachment) db.session.flush()
def _clone_attachment_folder(self, old_folder, new_object): folder_attrs = get_simple_column_attrs(AttachmentFolder) attachment_attrs = (get_simple_column_attrs(Attachment) | {'user'}) - {'modified_dt'} folder = AttachmentFolder(object=new_object) folder.populate_from_attrs(old_folder, folder_attrs) folder.acl_entries = clone_principals(AttachmentFolderPrincipal, old_folder.acl_entries, self._event_role_map, self._regform_map) for old_attachment in old_folder.attachments: self._attachment_map[old_attachment] = attachment = Attachment( folder=folder) attachment.populate_from_attrs(old_attachment, attachment_attrs) attachment.acl_entries = clone_principals( AttachmentPrincipal, old_attachment.acl_entries, self._event_role_map, self._regform_map) if attachment.type == AttachmentType.file: old_file = old_attachment.file attachment.file = AttachmentFile( attachment=attachment, user=old_file.user, filename=old_file.filename, content_type=old_file.content_type) with old_file.open() as fd: attachment.file.save(fd) return folder
def test_acls(dummy_event, dummy_contribution, dummy_user, create_user, obj_type): from .schemas import ACLSchema class TestSchema(ACLSchema, mm.Schema): pass if obj_type == 'event': obj = dummy_event elif obj_type == 'contrib': obj = dummy_contribution elif obj_type == 'subcontrib': obj = SubContribution(contribution=dummy_contribution, title='Test', duration=timedelta(minutes=10)) elif obj_type == 'attachment': folder = AttachmentFolder(title='Dummy Folder', description='a dummy folder') obj = Attachment(folder=folder, user=dummy_user, title='Dummy Attachment', type=AttachmentType.link, link_url='https://example.com') obj.folder.object = dummy_event elif obj_type == 'note': obj = EventNote(object=dummy_event) obj.create_revision(RenderMode.html, 'this is a dummy note', dummy_user) def assert_acl(expected_read_acl): __tracebackhide__ = True data = schema.dump(obj) read_acl = data['_access'].pop('read', None) assert data == { '_access': { 'delete': ['IndicoAdmin'], 'owner': ['IndicoAdmin'], 'update': ['IndicoAdmin'] } } if read_acl is not None: read_acl = set(read_acl) assert read_acl == expected_read_acl schema = TestSchema() user = create_user(1, email='*****@*****.**') # everything is public assert_acl(None) # event is protected and the acl is empty (nobody has regular access) dummy_event.protection_mode = ProtectionMode.protected assert_acl({'IndicoAdmin'}) # user on the acl has access dummy_event.update_principal(user, read_access=True) assert_acl({'IndicoAdmin', 'User:1'})
def dummy_attachment(dummy_user): folder = AttachmentFolder(title='dummy_folder', description='a dummy folder') file_ = AttachmentFile(user=dummy_user, filename='dummy_file.txt', content_type='text/plain') return Attachment(folder=folder, user=dummy_user, title='dummy_attachment', type=AttachmentType.file, file=file_)
def _process(self): form = AttachmentFolderForm(obj=FormDefaults(is_always_visible=True), linked_object=self.object) if form.validate_on_submit(): folder = AttachmentFolder(object=self.object) form.populate_obj(folder, skip={'acl'}) if folder.is_self_protected: folder.acl = form.acl.data db.session.add(folder) logger.info('Folder %s created by %s', folder, session.user) signals.attachments.folder_created.send(folder, user=session.user) flash(_("Folder \"{name}\" created").format(name=folder.title), 'success') return jsonify_data(attachment_list=_render_attachment_list(self.object)) return jsonify_template('attachments/create_folder.html', form=form, protection_message=_render_protection_message(self.object))
def _make_attachment(user, obj): folder = AttachmentFolder(title='dummy_folder', description='a dummy folder') file = AttachmentFile(user=user, filename='dummy_file.txt', content_type='text/plain') attachment = Attachment(folder=folder, user=user, title='dummy_attachment', type=AttachmentType.file, file=file) attachment.folder.object = obj attachment.file.save(BytesIO(b'hello world')) return attachment
def _clone_attachment_folder(self, old_folder, new_object): folder_attrs = get_simple_column_attrs(AttachmentFolder) | {'acl'} attachment_attrs = (get_simple_column_attrs(Attachment) | {'user', 'acl'}) - {'modified_dt'} folder = AttachmentFolder(object=new_object) folder.populate_from_attrs(old_folder, folder_attrs) for old_attachment in old_folder.attachments: attachment = Attachment(folder=folder) attachment.populate_from_attrs(old_attachment, attachment_attrs) if attachment.type == AttachmentType.file: old_file = old_attachment.file attachment.file = AttachmentFile(attachment=attachment, user=old_file.user, filename=old_file.filename, content_type=old_file.content_type) with old_file.open() as fd: attachment.file.save(fd)
def _folder_from_material(self, material, linked_object): folder_obj = AttachmentFolder(id=self._get_id(AttachmentFolder), title=convert_to_unicode(material.title).strip() or 'Material', description=convert_to_unicode(material.description), linked_object=linked_object, is_always_visible=not getattr(material._Material__ac, '_hideFromUnauthorizedUsers', False)) folder = _sa_to_dict(folder_obj) self.todo[AttachmentFolder].append(folder) tmp = ProtectionTarget() protection_from_ac(tmp, material._Material__ac) self.todo[AttachmentFolderPrincipal] += tmp.make_principal_rows(folder_id=folder['id']) folder['protection_mode'] = tmp.protection_mode return folder
def _process(self): params = self._getRequestParams() if params["title"] == "": params["title"] = "No Title" # change number of dates (lecture) if self._confirm == True: if self._event_type != "simple_event": c = self._createEvent(self._params) self.alertCreation([c]) # lectures else: lectures = [] for i in range(1, int(self._params["nbDates"]) + 1): self._params["sDay"] = self._params.get("sDay_%s" % i, "") self._params["sMonth"] = self._params.get( "sMonth_%s" % i, "") self._params["sYear"] = self._params.get( "sYear_%s" % i, "") self._params["sHour"] = self._params.get( "sHour_%s" % i, "") self._params["sMinute"] = self._params.get( "sMinute_%s" % i, "") self._params["duration"] = int( self._params.get("dur_%s" % i, 60)) lectures.append(self._createEvent(self._params)) self.alertCreation(lectures) lectures.sort(sortByStartDate) # create links for i, source in enumerate(lectures, 1): if len(lectures) > 1: source.setTitle("{} ({}/{})".format( source.getTitle(), i, len(lectures))) for j, target in enumerate(lectures, 1): if j != i: folder = AttachmentFolder(linked_object=source, title="part{}".format(j)) link = Attachment(user=session.user, type=AttachmentType.link, folder=folder, title="Part {}".format(j), link_url=target.getURL()) db.session.add(link) c = lectures[0] self._redirect(urlHandlers.UHConferenceModification.getURL(c)) else: url = urlHandlers.UHCategoryDisplay.getURL(self._target) self._redirect(url)
def _create_material(self, logs): folder = AttachmentFolder.find_first(object=self.event, is_default=False, title='Chat Logs', is_deleted=False) if folder is None: folder = AttachmentFolder(protection_mode=ProtectionMode.protected, linked_object=self.event, title='Chat Logs', description='Chat logs for this event') db.session.add(folder) filename = '{}.html'.format(secure_filename(self.material_name, 'logs')) attachment = Attachment( folder=folder, user=session.user, title=self.material_name, type=AttachmentType.file, description="Chat logs for the chat room '{}'".format( self.chatroom.name)) attachment.file = AttachmentFile(user=session.user, filename=filename, content_type='text/html') attachment.file.save(logs.encode('utf-8')) db.session.flush() signals.attachments.attachment_created.send(attachment, user=session.user) log_data = [ ('Range', 'Everything' if not self.date_filter else '{} - {}'.format( format_date(self.start_date), format_date(self.end_date))), ] self.event.log(EventLogRealm.management, EventLogKind.positive, 'Chat', 'Created material: {}'.format(filename), session.user, data=log_data)
def test_attachment_acls(dummy_event, dummy_user, create_user): from .schemas import ACLSchema class TestSchema(ACLSchema, mm.Schema): pass folder = AttachmentFolder(title='Dummy Folder', description='a dummy folder') attachment = Attachment(folder=folder, user=dummy_user, title='Dummy Attachment', type=AttachmentType.link, link_url='https://example.com') attachment.folder.object = dummy_event def assert_acl(expected_read_acl): __tracebackhide__ = True data = schema.dump(attachment) read_acl = data['_access'].pop('read', None) assert data == { '_access': { 'delete': ['IndicoAdmin'], 'owner': ['IndicoAdmin'], 'update': ['IndicoAdmin'] } } if read_acl is not None: read_acl = set(read_acl) assert read_acl == expected_read_acl schema = TestSchema() u1 = create_user(1, email='*****@*****.**') u2 = create_user(2, email='*****@*****.**') u3 = create_user(3, email='*****@*****.**') # event is inheriting public, so no acl assert_acl(None) # event is protected and the acl is empty (nobody has regular access) dummy_event.protection_mode = ProtectionMode.protected assert_acl({'IndicoAdmin'}) dummy_event.update_principal(u1, read_access=True) dummy_event.category.update_principal(u2, read_access=True) dummy_event.category.parent.update_principal(u3, read_access=True) # self-protected, so no acl inherited assert_acl({'IndicoAdmin', 'User:1'}) # event is inheriting from public categories, so there is no acl dummy_event.protection_mode = ProtectionMode.inheriting assert_acl(None) # event it itself public, so no acl here as well dummy_event.protection_mode = ProtectionMode.public assert_acl(None) # inheriting, so all parent acl entries dummy_event.protection_mode = ProtectionMode.inheriting dummy_event.category.parent.protection_mode = ProtectionMode.protected assert_acl({'IndicoAdmin', 'User:1', 'User:2', 'User:3'}) # category protected, so no parent category acl inherited dummy_event.category.protection_mode = ProtectionMode.protected assert_acl({'IndicoAdmin', 'User:1', 'User:2'}) # parent category acl entry is a manager, that one is inherited dummy_event.category.parent.update_principal(u3, full_access=True) assert_acl({'IndicoAdmin', 'User:1', 'User:2', 'User:3'}) # attachment self-protected, only the category/event manager has access folder.update_principal(u2, read_access=True) attachment.protection_mode = ProtectionMode.protected assert_acl({'IndicoAdmin', 'User:3'}) # the user in the attachment acl has access as well attachment.update_principal(u1, read_access=True) attachment.protection_mode = ProtectionMode.protected assert_acl({'IndicoAdmin', 'User:3', 'User:1'}) # attachment inheriting from self-protected folder - only the folder acl is used attachment.protection_mode = ProtectionMode.inheriting folder.protection_mode = ProtectionMode.protected assert_acl({'IndicoAdmin', 'User:3', 'User:2'})
def test_dump_attachment(db, dummy_user, dummy_contribution): from .schemas import AttachmentRecordSchema folder = AttachmentFolder(title='Dummy Folder', description='a dummy folder') file = AttachmentFile(user=dummy_user, filename='dummy_file.txt', content_type='text/plain') attachment = Attachment(folder=folder, user=dummy_user, title='Dummy Attachment', type=AttachmentType.file, file=file) attachment.folder.object = dummy_contribution attachment.file.save(BytesIO(b'hello world')) db.session.flush() category_id = dummy_contribution.event.category_id schema = AttachmentRecordSchema(context={'schema': 'test-attachment'}) assert schema.dump(attachment) == { '$schema': 'test-attachment', '_access': { 'delete': ['IndicoAdmin'], 'owner': ['IndicoAdmin'], 'update': ['IndicoAdmin'], }, '_data': { 'filename': 'dummy_file.txt', 'site': 'http://localhost', 'title': 'Dummy Attachment', 'persons': { 'name': 'Guinea Pig' }, }, 'attachment_id': attachment.id, 'category_id': category_id, 'category_path': [ { 'id': 0, 'title': 'Home', 'url': '/' }, { 'id': category_id, 'title': 'dummy', 'url': f'/category/{category_id}/' }, ], 'contribution_id': dummy_contribution.id, 'event_id': 0, 'folder_id': folder.id, 'modified_dt': attachment.modified_dt.isoformat(), 'type': 'attachment', 'type_format': 'file', 'url': (f'http://localhost/event/0/contributions/' f'{dummy_contribution.id}/attachments/{folder.id}/{attachment.id}/dummy_file.txt' ), }
def test_dump_attachment(db, dummy_user, dummy_contribution): from indico.modules.search.schemas import AttachmentSchema folder = AttachmentFolder(title='Dummy Folder', description='a dummy folder') file = AttachmentFile(user=dummy_user, filename='dummy_file.txt', content_type='text/plain') attachment = Attachment(folder=folder, user=dummy_user, title='Dummy Attachment', type=AttachmentType.file, file=file) attachment.folder.object = dummy_contribution attachment.file.save(BytesIO(b'hello world')) db.session.flush() category_id = dummy_contribution.event.category_id schema = AttachmentSchema() assert schema.dump(attachment) == { 'filename': 'dummy_file.txt', 'title': 'Dummy Attachment', 'user': { 'affiliation': None, 'name': 'Guinea Pig' }, 'attachment_id': attachment.id, 'attachment_type': 'file', 'category_id': category_id, 'category_path': [ { 'id': 0, 'title': 'Home', 'url': '/' }, { 'id': category_id, 'title': 'dummy', 'url': f'/category/{category_id}/' }, ], 'contribution_id': dummy_contribution.id, 'subcontribution_id': None, 'event_id': 0, 'folder_id': folder.id, 'modified_dt': attachment.modified_dt.isoformat(), 'type': 'attachment', 'url': (f'/event/0/contributions/' f'{dummy_contribution.id}/attachments/{folder.id}/{attachment.id}/dummy_file.txt' ), }