Пример #1
0
def _merge_users(target, source, **kwargs):
    from indico.modules.attachments.models.attachments import Attachment, AttachmentFile
    from indico.modules.attachments.models.principals import AttachmentPrincipal, AttachmentFolderPrincipal
    Attachment.find(user_id=source.id).update({Attachment.user_id: target.id})
    AttachmentFile.find(user_id=source.id).update({AttachmentFile.user_id: target.id})
    AttachmentPrincipal.merge_users(target, source, 'attachment')
    AttachmentFolderPrincipal.merge_users(target, source, 'folder')
Пример #2
0
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
Пример #3
0
    def _process(self):
        defaults = FormDefaults(self.attachment,
                                protected=self.attachment.is_self_protected,
                                skip_attrs={'file'})
        if self.attachment.type == AttachmentType.file:
            form = EditAttachmentFileForm(linked_object=self.object,
                                          obj=defaults,
                                          file=self.attachment)
        else:
            form = EditAttachmentLinkForm(linked_object=self.object,
                                          obj=defaults)

        if form.validate_on_submit():
            folder = form.folder.data or AttachmentFolder.get_or_create_default(
                linked_object=self.object)
            logger.info('Attachment %s edited by %s', self.attachment,
                        session.user)
            form.populate_obj(self.attachment, skip={'acl', 'file'})
            self.attachment.folder = folder
            if self.attachment.is_self_protected:
                # can't use `=` because of https://bitbucket.org/zzzeek/sqlalchemy/issues/3583
                self.attachment.acl |= form.acl.data
                self.attachment.acl &= form.acl.data
            # files need special handling; links are already updated in `populate_obj`
            if self.attachment.type == AttachmentType.file:
                file = form.file.data['added']
                if file:
                    self.attachment.file = AttachmentFile(
                        user=session.user,
                        content_type=file.mimetype,
                        filename=secure_filename(file.filename, 'attachment'))
                    self.attachment.file.save(file.stream)

            signals.attachments.attachment_updated.send(self.attachment,
                                                        user=session.user)
            flash(
                _("The attachment \"{name}\" has been updated").format(
                    name=self.attachment.title), 'success')
            return jsonify_data(
                attachment_list=_render_attachment_list(self.object))

        template = ('attachments/upload.html' if self.attachment.type
                    == AttachmentType.file else 'attachments/add_link.html')
        return jsonify_template(
            template,
            form=form,
            existing_attachment=self.attachment,
            action=url_for('.modify_attachment', self.attachment),
            protection_message=_render_protection_message(self.object),
            folders_protection_info=_get_folders_protection_info(self.object))
Пример #4
0
def create_contribution_from_abstract(abstract, contrib_session=None):
    from indico.modules.events.abstracts.settings import abstracts_settings

    event = abstract.event
    contrib_person_links = set()
    person_link_attrs = {
        '_title', 'address', 'affiliation', 'first_name', 'last_name', 'phone',
        'author_type', 'is_speaker', 'display_order'
    }
    for abstract_person_link in abstract.person_links:
        link = ContributionPersonLink(person=abstract_person_link.person)
        link.populate_from_attrs(abstract_person_link, person_link_attrs)
        contrib_person_links.add(link)

    if contrib_session:
        duration = contrib_session.default_contribution_duration
    else:
        duration = contribution_settings.get(event, 'default_duration')
    custom_fields_data = {
        'custom_{}'.format(field_value.contribution_field.id): field_value.data
        for field_value in abstract.field_values
    }
    contrib = create_contribution(event, {
        'friendly_id': abstract.friendly_id,
        'title': abstract.title,
        'duration': duration,
        'description': abstract.description,
        'type': abstract.accepted_contrib_type,
        'track': abstract.accepted_track,
        'session': contrib_session,
        'person_link_data': {link: True
                             for link in contrib_person_links}
    },
                                  custom_fields_data=custom_fields_data)
    if abstracts_settings.get(event, 'copy_attachments') and abstract.files:
        folder = AttachmentFolder.get_or_create_default(contrib)
        for abstract_file in abstract.files:
            attachment = Attachment(user=abstract.submitter,
                                    type=AttachmentType.file,
                                    folder=folder,
                                    title=abstract_file.filename)
            attachment.file = AttachmentFile(
                user=abstract.submitter,
                filename=abstract_file.filename,
                content_type=abstract_file.content_type)
            with abstract_file.open() as fd:
                attachment.file.save(fd)
    db.session.flush()
    return contrib
Пример #5
0
 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)
     for old_attachment in old_folder.attachments:
         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)
         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)
Пример #6
0
 def _process(self):
     from indico_conversion.plugin import ConversionPlugin
     try:
         payload = secure_serializer.loads(request.form['directory'],
                                           salt='pdf-conversion')
     except BadData:
         ConversionPlugin.logger.exception('Received invalid payload (%s)',
                                           request.form['directory'])
         return jsonify(success=False)
     attachment = Attachment.get(payload['attachment_id'])
     if not attachment or attachment.is_deleted or attachment.folder.is_deleted:
         ConversionPlugin.logger.info('Attachment has been deleted: %s',
                                      attachment)
         return jsonify(success=True)
     elif request.form['status'] != '1':
         ConversionPlugin.logger.error('Received invalid status %s for %s',
                                       request.form['status'], attachment)
         return jsonify(success=False)
     name, ext = os.path.splitext(attachment.file.filename)
     title = get_pdf_title(attachment)
     pdf_attachment = Attachment(folder=attachment.folder,
                                 user=attachment.user,
                                 title=title,
                                 description=attachment.description,
                                 type=AttachmentType.file,
                                 protection_mode=attachment.protection_mode,
                                 acl=attachment.acl)
     # TODO: remove first case when Conversion Server is fully on new version
     if 'content' in request.form:
         # handling of legacy API
         data = BytesIO(base64.decodestring(request.form['content']))
     else:
         filepdf = request.files['content']
         data = filepdf.stream.read()
     pdf_attachment.file = AttachmentFile(user=attachment.file.user,
                                          filename='{}.pdf'.format(name),
                                          content_type='application/pdf')
     pdf_attachment.file.save(data)
     db.session.add(pdf_attachment)
     db.session.flush()
     cache.set(unicode(attachment.id), 'finished', timedelta(minutes=15))
     ConversionPlugin.logger.info('Added PDF attachment %s for %s',
                                  pdf_attachment, attachment)
     signals.attachments.attachment_created.send(pdf_attachment, user=None)
     return jsonify(success=True)
Пример #7
0
 def _process(self):
     form = AddAttachmentFilesForm(linked_object=self.object)
     if form.validate_on_submit():
         files = form.files.data
         folder = form.folder.data or AttachmentFolder.get_or_create_default(
             linked_object=self.object)
         for f in files:
             filename = secure_client_filename(f.filename)
             attachment = Attachment(
                 folder=folder,
                 user=session.user,
                 title=f.filename,
                 type=AttachmentType.file,
                 protection_mode=form.protection_mode.data)
             if attachment.is_self_protected:
                 attachment.acl = form.acl.data
             content_type = mimetypes.guess_type(
                 f.filename)[0] or f.mimetype or 'application/octet-stream'
             attachment.file = AttachmentFile(user=session.user,
                                              filename=filename,
                                              content_type=content_type)
             attachment.file.save(f.stream)
             db.session.add(attachment)
             db.session.flush()
             logger.info('Attachment %s uploaded by %s', attachment,
                         session.user)
             signals.attachments.attachment_created.send(attachment,
                                                         user=session.user)
         flash(
             ngettext("The attachment has been uploaded",
                      "{count} attachments have been uploaded",
                      len(files)).format(count=len(files)), 'success')
         return jsonify_data(
             attachment_list=_render_attachment_list(self.object))
     return jsonify_template(
         'attachments/upload.html',
         form=form,
         action=url_for('.upload', self.object),
         protection_message=_render_protection_message(self.object),
         folders_protection_info=_get_folders_protection_info(self.object),
         existing_attachment=None)
Пример #8
0
    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)
Пример #9
0
    def _process(self):
        defaults = FormDefaults(self.attachment,
                                protected=self.attachment.is_protected,
                                skip_attrs={'file'})
        if self.attachment.type == AttachmentType.file:
            file_ = self.attachment.file
            # file_attrs has to be manually "serialized", since it's going to be converted to JSON
            file_attrs = {
                'url':
                url_for('attachments.download',
                        self.attachment,
                        filename=self.attachment.file.filename,
                        from_preview='1'),
                'filename':
                file_.filename,
                'size':
                file_.size,
                'content_type':
                file_.content_type
            }
            form = EditAttachmentFileForm(linked_object=self.object,
                                          obj=defaults,
                                          file=file_attrs)
        else:
            form = EditAttachmentLinkForm(linked_object=self.object,
                                          obj=defaults)

        if form.validate_on_submit():
            folder = form.folder.data or AttachmentFolder.get_or_create_default(
                linked_object=self.object)
            logger.info('Attachment {} edited by {}'.format(
                self.attachment, session.user))
            form.populate_obj(self.attachment, skip={'acl', 'file'})
            self.attachment.folder = folder
            if self.attachment.is_protected:
                # can't use `=` because of https://bitbucket.org/zzzeek/sqlalchemy/issues/3583
                self.attachment.acl |= form.acl.data
                self.attachment.acl &= form.acl.data
            # files need special handling; links are already updated in `populate_obj`
            if self.attachment.type == AttachmentType.file:
                file = request.files['file'] if request.files else None
                if file:
                    self.attachment.file = AttachmentFile(
                        user=session.user,
                        content_type=file.mimetype,
                        filename=secure_filename(file.filename, 'attachment'))
                    self.attachment.file.save(file.file)

            signals.attachments.attachment_updated.send(self.attachment,
                                                        user=session.user)
            flash(
                _("The attachment \"{name}\" has been updated").format(
                    name=self.attachment.title), 'success')
            return jsonify_data(
                attachment_list=_render_attachment_list(self.object))

        template = ('attachments/upload.html' if self.attachment.type
                    == AttachmentType.file else 'attachments/add_link.html')
        return jsonify_template(
            template,
            form=form,
            existing_attachment=self.attachment,
            action=url_for('.modify_attachment', self.attachment),
            protection_message=_render_protection_message(self.object),
            folders_protection_info=_get_folders_protection_info(self.object))
Пример #10
0
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_)
Пример #11
0
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'
         ),
    }
Пример #12
0
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'
         ),
    }