Ejemplo n.º 1
0
    def reply(self):

        userid = self.request.form.get('userid')
        if not userid:
            return self.error(message='Missing userid.')

        file_ = self.request.form.get('file')
        if not file_:
            return self.error(message='Missing file.')

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        try:
            adopt_user = api.env.adopt_user(username=userid)
        except api.exc.UserNotFoundError:
            return self.error(status=404, message='Unknown user.')

        with adopt_user:
            destination = self.destination()
            if destination:
                # XXX - Duck typing as error handling
                # We've encountered an error while discovering a destination
                if isinstance(destination, dict):
                    return destination
                filename = file_.filename.decode('utf8')
                command = CreateDocumentCommand(destination, filename, file_)
                with elevated_privileges():
                    command.execute()

        self.request.response.setStatus(201)
        return super(ScanIn, self).reply()
Ejemplo n.º 2
0
    def reply(self):

        userid = self.request.form.get('userid')
        if not userid:
            return self.error(message='Missing userid.')

        file_ = self.request.form.get('file')
        if not file_:
            return self.error(message='Missing file.')

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        try:
            adopt_user = api.env.adopt_user(username=userid)
        except api.exc.UserNotFoundError:
            return self.error(status=404, message='Unknown user.')

        with adopt_user:
            destination = self.destination()
            if destination:
                # XXX - Duck typing as error handling
                # We've encountered an error while discovering a destination
                if isinstance(destination, dict):
                    return destination
                filename = file_.filename.decode('utf8')
                command = CreateDocumentCommand(destination, filename, file_)
                with elevated_privileges():
                    command.execute()

        self.request.response.setStatus(201)
        return super(ScanIn, self).reply()
Ejemplo n.º 3
0
    def reply(self):

        userid = self.request.form.get('userid')
        if not userid:
            return self.error(message='Missing userid.')

        file_ = self.request.form.get('file')
        if not file_:
            return self.error(message='Missing file.')

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        try:
            adopt_user = api.env.adopt_user(username=userid)
        except api.exc.UserNotFoundError:
            return self.error(message='Unknown user.')

        with adopt_user:
            destination = self.destination()
            if destination is None:
                return self.error(message='Destination does not exist.')
            filename = file_.filename.decode('utf8')
            command = CreateDocumentCommand(destination, filename, file_)
            command.execute()

        self.request.response.setStatus(201)
        return super(ScanIn, self).reply()
Ejemplo n.º 4
0
    def create_destination_document(self):
        # get all the metadata that will be set on the created file.
        # We blacklist some fields that should not be copied
        fields_to_skip = set(("file",
                              "archival_file",
                              "archival_file_state",
                              "thumbnail",
                              "preview",
                              "digitally_available",
                              "changeNote",
                              "changed",
                              "relatedItems",))
        metadata = {}
        for schema in iterSchemataForType(self.context.portal_type):
            for name, schema_field in getFieldsInOrder(schema):
                if name in fields_to_skip:
                    continue
                field_instance = schema_field.bind(self.context)
                metadata[name] = field_instance.get(self.context)

        command = CreateDocumentCommand(self.destination, None, None, **metadata)
        destination_document = command.execute()

        # We make it in shadow state until its file is set by the callback view
        destination_document.as_shadow_document()
        # Add marker interface. This should be useful in the future for
        # cleanup jobs, retries if the PDF was not delivered and so on.
        alsoProvides(destination_document, IDocumentSavedAsPDFMarker)
        # Add annotations needed for the SavePDFDocumentUnder view.
        annotations = IAnnotations(destination_document)
        annotations[PDF_SAVE_SOURCE_UUID_KEY] = IUUID(self.context)
        annotations[PDF_SAVE_SOURCE_VERSION_KEY] = self.version_id

        # The missing_value attribute of a z3c-form field is used
        # as soon as an object has no default_value i.e. after creating
        # an object trough the command-line.
        #
        # Because the relatedItems field needs a list as a missing_value,
        # we will fall into the "mutable keyword argument"-python gotcha.
        # The relatedItems will be shared between the object-instances.
        #
        # Unfortunately the z3c-form field does not provide a
        # missing_value-factory (like the defaultFactory) which would be
        # necessary to fix this issue properly.
        #
        # As a workaround we make sure that the new document's relatedItems
        # is different object from the source document's.
        IRelatedDocuments(destination_document).relatedItems = list(
            IRelatedDocuments(destination_document).relatedItems)

        IRelatedDocuments(destination_document).relatedItems.append(
            RelationValue(getUtility(IIntIds).getId(self.context)))

        msg = _(u'Document ${document} was successfully created in ${destination}',
                mapping={"document": destination_document.title, "destination": self.destination.title})
        api.portal.show_message(msg, self.request, type='info')

        return destination_document
Ejemplo n.º 5
0
    def test_create_document_from_command(self):
        self.login(self.regular_user)
        command = CreateDocumentCommand(
            self.dossier, 'testm\xc3\xa4il.txt', 'buh!', title='\xc3\x9cnicode')
        document = command.execute()

        self.assertIsInstance(document.title, unicode)
        self.assertEqual(u'\xdcnicode', document.title)
        self.assertEqual('buh!', document.file.data)
        self.assertEqual('text/plain', document.file.contentType)
Ejemplo n.º 6
0
    def create_tasks_listing_pdf(self):
        """Creates a pdf representation of the dossier tasks, and add it to
        the dossier as a normal document.

        If the dossiers has an end date use that date as the document date.
        This prevents the dossier from entering an invalid state with a
        document date outside the dossiers start-end range.
        """
        if not self.get_property('tasks_pdf_enabled'):
            return

        view = self.context.unrestrictedTraverse('pdf-dossier-tasks')

        today = api.portal.get_localized_time(datetime=datetime.today(),
                                              long_format=True)
        filename = u'Tasks {}.pdf'.format(today)
        title = _(u'title_dossier_tasks',
                  default=u'Task list of dossier ${title}, ${timestamp}',
                  mapping={
                      'title': self.context.title,
                      'timestamp': today
                  })
        kwargs = {
            'preserved_as_paper': False,
        }
        dossier = IDossier(self.context)
        if dossier and dossier.end:
            kwargs['document_date'] = dossier.end

        results = api.content.find(object_provides=IDossierTasksPDFMarker,
                                   depth=1,
                                   context=self.context)

        with elevated_privileges():
            if len(results) > 0:
                document = results[0].getObject()
                document.title = translate(title, context=self.context.REQUEST)
                comment = _(
                    u'Updated with a newer generated version from dossier ${title}.',
                    mapping=dict(title=self.context.title))
                document.update_file(view.get_data(),
                                     create_version=True,
                                     comment=comment)
                return

            document = CreateDocumentCommand(
                self.context,
                filename,
                view.get_data(),
                title=translate(title, context=self.context.REQUEST),
                content_type='application/pdf',
                interfaces=[IDossierTasksPDFMarker],
                **kwargs).execute()
            document.reindexObject(idxs=['object_provides'])
Ejemplo n.º 7
0
    def test_create_document_from_command(self):
        self.login(self.regular_user)
        command = CreateDocumentCommand(self.dossier,
                                        'testm\xc3\xa4il.txt',
                                        'buh!',
                                        title='\xc3\x9cnicode')
        document = command.execute()

        self.assertIsInstance(document.title, unicode)
        self.assertEqual(u'\xdcnicode', document.title)
        self.assertEqual('buh!', document.file.data)
        self.assertEqual('text/plain', document.file.contentType)
Ejemplo n.º 8
0
    def create_tasks_listing_pdf(self):
        """Creates a pdf representation of the dossier tasks, and add it to
        the dossier as a normal document.

        If the dossiers has an end date use that date as the document date.
        This prevents the dossier from entering an invalid state with a
        document date outside the dossiers start-end range.
        """
        if not self.get_property('tasks_pdf_enabled'):
            return

        view = self.context.unrestrictedTraverse('pdf-dossier-tasks')

        today = api.portal.get_localized_time(
            datetime=datetime.today(), long_format=True)
        filename = u'Tasks {}.pdf'.format(today)
        title = _(u'title_dossier_tasks',
                  default=u'Task list of dossier ${title}, ${timestamp}',
                  mapping={'title': self.context.title,
                           'timestamp': today})
        kwargs = {
            'preserved_as_paper': False,
        }
        dossier = IDossier(self.context)
        if dossier and dossier.end:
            kwargs['document_date'] = dossier.end

        results = api.content.find(object_provides=IDossierTasksPDFMarker,
                                   depth=1,
                                   context=self.context)

        with elevated_privileges():
            if len(results) > 0:
                document = results[0].getObject()
                document.title = translate(title, context=self.context.REQUEST)
                comment = _(u'Updated with a newer generated version from dossier ${title}.',
                            mapping=dict(title=self.context.title))
                document.update_file(view.get_data(), create_version=True,
                                     comment=comment)
                return

            document = CreateDocumentCommand(
                self.context, filename, view.get_data(),
                title=translate(title, context=self.context.REQUEST),
                content_type='application/pdf',
                interfaces=[IDossierTasksPDFMarker],
                **kwargs).execute()
            document.reindexObject(idxs=['object_provides'])
Ejemplo n.º 9
0
    def schedule_ad_hoc(self, title):
        committee = self.committee.resolve_committee()
        ad_hoc_template = committee.get_ad_hoc_template()
        if not ad_hoc_template:
            raise MissingAdHocTemplate

        meeting_dossier = self.get_dossier()
        if not api.user.get_current().checkPermission(
                'opengever.document: Add document', meeting_dossier):
            raise MissingMeetingDossierPermissions

        document_title = _(u'title_ad_hoc_document',
                           default=u'Ad hoc agenda item ${title}',
                           mapping={u'title': title})

        ad_hoc_document = CreateDocumentCommand(
            context=meeting_dossier,
            filename=ad_hoc_template.file.filename,
            data=ad_hoc_template.file.data,
            content_type=ad_hoc_template.file.contentType,
            title=translate(document_title, context=getRequest())).execute()
        agenda_item = AgendaItem(title=title,
                                 document=ad_hoc_document,
                                 is_paragraph=False)

        self.agenda_items.append(agenda_item)
        self.reorder_agenda_items()
        return agenda_item
Ejemplo n.º 10
0
    def create_proposal_document(self, source_blob=None, **kwargs):
        """Creates a proposal document within this proposal or submitted
        proposal.
        Only one proposal document can be created.
        """
        if not is_word_meeting_implementation_enabled():
            raise WordMeetingImplementationDisabledError()

        if self.get_proposal_document():
            raise ValueError('There is already a proposal document.')

        if source_blob:
            kwargs.setdefault('filename', source_blob.filename)
            kwargs.setdefault('data', source_blob.open().read())
            kwargs.setdefault('content_type', source_blob.contentType)

        kwargs['context'] = self
        kwargs.setdefault('preserved_as_paper', False)

        title = _(u'proposal_document_title',
                  default=u'Proposal document ${title}',
                  mapping={'title': safe_unicode(self.Title())})
        title = translate(title, context=self.REQUEST).strip()
        kwargs.setdefault('title', title)

        with elevated_privileges():
            obj = CreateDocumentCommand(**kwargs).execute()

        self._proposal_document_uuid = IUUID(obj)
        return obj
Ejemplo n.º 11
0
    def __call__(self, filename, title, description, content_type, data,
                 portal_type):
        """Quickupload description inputs are hidden in gever
        therefore we skip the description.
        """
        if self.is_email_upload(filename):
            command = CreateEmailCommand(
                self.context,
                filename,
                data,
                message_source=MESSAGE_SOURCE_DRAG_DROP_UPLOAD)
        else:
            command = CreateDocumentCommand(self.context, filename, data)

        try:
            obj = command.execute()
        except ForbiddenByQuota as exc:
            # this is an error, we must not commit
            transaction.abort()
            return {
                'error': translate(exc.message, context=self.context.REQUEST),
                'success': None
            }

        result = {'success': obj}
        return result
Ejemplo n.º 12
0
    def generate_excerpt(self, title):
        """Generate an excerpt from the agenda items document.

        Can either be an excerpt from the proposals document or an excerpt
        from the ad-hoc agenda items document.
        In both cases the excerpt is stored in the meeting dossier.
        """
        assert self.can_generate_excerpt()
        meeting_dossier = self.meeting.get_dossier()
        source_document = self.resolve_document()

        if not source_document:
            raise ValueError('The agenda item has no document.')

        if not api.user.get_current().checkPermission(
                'opengever.document: Add document', meeting_dossier):
            raise MissingMeetingDossierPermissions

        excerpt_document = CreateDocumentCommand(
            context=meeting_dossier,
            filename=source_document.file.filename,
            data=source_document.file.data,
            content_type=source_document.file.contentType,
            title=title).execute()

        if self.has_proposal:
            submitted_proposal = self.proposal.resolve_submitted_proposal()
            submitted_proposal.append_excerpt(excerpt_document)
        else:
            self.excerpts.append(Excerpt(
                excerpt_oguid=Oguid.for_object(excerpt_document)))

        return excerpt_document
Ejemplo n.º 13
0
    def create_journal_pdf(self):
        """Creates a pdf representation of the dossier journal, and add it to
        the dossier as a normal document.
        """
        if not self.get_property('journal_pdf_enabled'):
            return

        view = self.context.unrestrictedTraverse('pdf-dossier-journal')
        today = api.portal.get_localized_time(datetime=datetime.today(),
                                              long_format=True)
        filename = u'Journal {}.pdf'.format(today)
        title = _(u'title_dossier_journal',
                  default=u'Journal of dossier ${title}, ${timestamp}',
                  mapping={
                      'title': self.context.title,
                      'timestamp': today
                  })

        with elevated_privileges():
            CreateDocumentCommand(self.context,
                                  filename,
                                  view.get_data(),
                                  title=translate(
                                      title, context=self.context.REQUEST),
                                  content_type='application/pdf',
                                  preserved_as_paper=False).execute()
Ejemplo n.º 14
0
    def extract_attachment_into_parent(self, position):
        """Extract one specified attachment into the mails parent dossier or
        inbox.

        Also add a reference from all attached documents (*not* mails) to self.

        Position must be an integer attachment positions. The position
        can be obtained from the attachment description returned by
        `get_attachments`.
        """
        parent = self.get_extraction_parent()
        if parent is None:
            raise RuntimeError("Could not find a parent dossier or inbox for "
                               "{}".format(self.absolute_url()))

        data, content_type, filename = self._get_attachment_data(position)
        title = os.path.splitext(filename)[0]

        if content_type == 'message/rfc822':
            doc = CreateEmailCommand(parent,
                                     filename,
                                     data,
                                     title=title,
                                     content_type=content_type,
                                     digitally_available=True).execute()
        else:
            doc = CreateDocumentCommand(parent,
                                        filename,
                                        data,
                                        title=title,
                                        content_type=content_type,
                                        digitally_available=True).execute()

            # add a reference from the attachment to the mail
            intids = getUtility(IIntIds)
            iid = intids.getId(self)

            IRelatedDocuments(doc).relatedItems = [RelationValue(iid)]
            doc.reindexObject()

        return doc
Ejemplo n.º 15
0
    def schedule_ad_hoc(self, title, template_id=None, description=None):
        committee = self.committee.resolve_committee()

        if template_id is None:
            ad_hoc_template = committee.get_ad_hoc_template()
        else:
            from opengever.meeting.vocabulary import ProposalTemplatesForCommitteeVocabulary
            vocabulary_factory = ProposalTemplatesForCommitteeVocabulary()
            vocabulary = vocabulary_factory(committee)
            templates = [
                term.value for term in vocabulary
                if term.value.getId() == template_id
            ]
            assert 1 == len(templates)
            ad_hoc_template = templates[0]

        if not ad_hoc_template:
            raise MissingAdHocTemplate

        meeting_dossier = self.get_dossier()
        if not api.user.get_current().checkPermission(
                'opengever.document: Add document', meeting_dossier):
            raise MissingMeetingDossierPermissions

        ad_hoc_document = CreateDocumentCommand(
            context=meeting_dossier,
            filename=ad_hoc_template.file.filename,
            data=ad_hoc_template.file.data,
            content_type=ad_hoc_template.file.contentType,
            title=title).execute()
        agenda_item = AgendaItem(title=title,
                                 description=description,
                                 document=ad_hoc_document,
                                 is_paragraph=False)

        self.agenda_items.append(agenda_item)
        self.reorder_agenda_items()
        return agenda_item
Ejemplo n.º 16
0
    def create_proposal_document(self, source_blob=None, **kwargs):
        """Creates a proposal document within this proposal or submitted
        proposal.
        Only one proposal document can be created.
        """
        if self.get_proposal_document():
            raise ValueError('There is already a proposal document.')

        if source_blob:
            kwargs.setdefault('filename', source_blob.filename)
            kwargs.setdefault('data', source_blob.open().read())
            kwargs.setdefault('content_type', source_blob.contentType)

        kwargs['context'] = self
        kwargs.setdefault('preserved_as_paper', False)

        kwargs.setdefault('title', safe_unicode(self.Title()))

        with elevated_privileges():
            obj = CreateDocumentCommand(**kwargs).execute()

        self._proposal_document_uuid = IUUID(obj)
        return obj
Ejemplo n.º 17
0
    def create_journal_pdf(self):
        """Creates a pdf representation of the dossier journal, and add it to
        the dossier as a normal document.

        If the dossiers has an end date use that date as the document date.
        This prevents the dossier from entering an invalid state with a
        document date outside the dossiers start-end range.
        """
        if not self.get_property('journal_pdf_enabled'):
            return

        view = self.context.unrestrictedTraverse('pdf-dossier-journal')
        today = api.portal.get_localized_time(datetime=datetime.today(),
                                              long_format=True)
        filename = u'Journal {}.pdf'.format(today)
        title = _(u'title_dossier_journal',
                  default=u'Journal of dossier ${title}, ${timestamp}',
                  mapping={
                      'title': self.context.title,
                      'timestamp': today
                  })
        kwargs = {
            'preserved_as_paper': False,
        }
        dossier = IDossier(self.context)
        if dossier and dossier.end:
            kwargs['document_date'] = dossier.end

        with elevated_privileges():
            CreateDocumentCommand(self.context,
                                  filename,
                                  view.get_data(),
                                  title=translate(
                                      title, context=self.context.REQUEST),
                                  content_type='application/pdf',
                                  **kwargs).execute()
Ejemplo n.º 18
0
    def create_destination_document(self):
        # get all the metadata that will be set on the created file.
        # We blacklist some fields that should not be copied
        fields_to_skip = set((
            "file",
            "archival_file",
            "archival_file_state",
            "thumbnail",
            "preview",
            "digitally_available",
            "changeNote",
            "changed",
            "relatedItems",
        ))
        metadata = {}
        for schema in iterSchemataForType(self.context.portal_type):
            for name, schema_field in getFieldsInOrder(schema):
                if name in fields_to_skip:
                    continue
                field_instance = schema_field.bind(self.context)
                metadata[name] = field_instance.get(self.context)

        command = CreateDocumentCommand(self.destination, None, None,
                                        **metadata)
        destination_document = command.execute()

        # We make it in shadow state until its file is set by the callback view
        destination_document.as_shadow_document()
        # Add marker interface. This should be useful in the future for
        # cleanup jobs, retries if the PDF was not delivered and so on.
        alsoProvides(destination_document, IDocumentSavedAsPDFMarker)
        # Add annotations needed for the SavePDFDocumentUnder view.
        annotations = IAnnotations(destination_document)
        annotations[PDF_SAVE_SOURCE_UUID_KEY] = IUUID(self.context)
        annotations[PDF_SAVE_SOURCE_VERSION_KEY] = self.version_id

        # The missing_value attribute of a z3c-form field is used
        # as soon as an object has no default_value i.e. after creating
        # an object trough the command-line.
        #
        # Because the relatedItems field needs a list as a missing_value,
        # we will fall into the "mutable keyword argument"-python gotcha.
        # The relatedItems will be shared between the object-instances.
        #
        # Unfortunately the z3c-form field does not provide a
        # missing_value-factory (like the defaultFactory) which would be
        # necessary to fix this issue properly.
        #
        # As a workaround we make sure that the new document's relatedItems
        # is different object from the source document's.
        IRelatedDocuments(destination_document).relatedItems = list(
            IRelatedDocuments(destination_document).relatedItems)

        IRelatedDocuments(destination_document).relatedItems.append(
            RelationValue(getUtility(IIntIds).getId(self.context)))

        msg = _(
            u'Document ${document} was successfully created in ${destination}',
            mapping={
                "document": destination_document.title,
                "destination": self.destination.title
            })
        api.portal.show_message(msg, self.request, type='info')

        return destination_document