Example #1
0
def containing_subdossier(obj):
    """Returns the title of the subdossier the object is contained in,
    unless it's contained directly in the root of a dossier, in which
    case an empty string is returned.
    """
    context = aq_inner(obj)
    # Only compute for types that actually can be contained in a dossier
    if not context.portal_type in ['opengever.document.document',
                                   'opengever.task.task',
                                   'ftw.mail.mail']:
        return ''

    parent = context
    parent_dossier = None
    parent_dossier_found = False
    while not parent_dossier_found:
        parent = aq_parent(parent)
        if ISiteRoot.providedBy(parent):
            # Shouldn't happen, just to be safe
            break
        if IDossierMarker.providedBy(parent):
            parent_dossier_found = True
            parent_dossier = parent

    if IDossierMarker.providedBy(aq_parent(parent_dossier)):
        # parent dossier is a subdossier
        return parent_dossier.Title()
    return ''
Example #2
0
def containing_subdossier(obj):
    """Returns the title of the subdossier the object is contained in,
    unless it's contained directly in the root of a dossier, in which
    case an empty string is returned.
    """
    if obj.portal_type not in TYPES_WITH_CONTAINING_SUBDOSSIER_INDEX:
        return ''

    context = aq_inner(obj)

    parent = context
    parent_dossier = None
    parent_dossier_found = False
    while not parent_dossier_found:
        parent = aq_parent(parent)
        if ISiteRoot.providedBy(parent):
            # Shouldn't happen, just to be safe
            break
        if IDossierMarker.providedBy(parent):
            parent_dossier_found = True
            parent_dossier = parent

    if IDossierMarker.providedBy(aq_parent(parent_dossier)):
        # parent dossier is a subdossier
        return parent_dossier.Title()
    return ''
    def test_one_of_the_parents_of_content_needs_to_be_a_dossier(self):
        self.login(self.regular_user)
        self.assertTrue(IDossierMarker.providedBy(aq_parent(self.document)))
        self.assertTrue(can_access_archival_file_form(self.regular_user, self.document))

        self.assertFalse(IDossierMarker.providedBy(aq_parent(self.taskdocument)))
        self.assertTrue(can_access_archival_file_form(self.regular_user, self.taskdocument))

        self.login(self.administrator)
        self.assertFalse(can_access_archival_file_form(self.administrator, self.inbox_document))
Example #4
0
def object_moved_or_added(context, event):
    if isinstance(event, ObjectAddedEvent):
        # Don't consider moving or removing an object a "touch". Mass-moves
        # would immediately fill up the touched log, and removals should not
        # be tracked anyway.
        if should_track_touches(context):
            notify(ObjectTouchedEvent(context))

    if IObjectRemovedEvent.providedBy(event):
        return

    # Update object security after moving or copying.
    # Specifically, this is needed for the case where an object is moved out
    # of a location where a Placeful Workflow Policy applies to a location
    # where it doesn't.
    #
    #  Plone then no longer provides the placeful workflow for that object,
    # but doesn't automatically update the object's security.
    #
    # We use ftw.upgrade's update_security_for() here to correctly
    # recalculate security, but do the reindexing ourselves because otherwise
    # Plone will do it recursively (unnecessarily so).
    changed = update_security_for(context, reindex_security=False)
    if changed:
        reindex_object_security_without_children(context)

    # There are several indices that need updating when a dossier is moved.
    # first make sure obj was actually moved and not created
    if not event.oldParent or not event.newParent:
        return

    # When an object is moved, its containing_dossier needs reindexing.
    to_reindex = ['containing_dossier']
    # containing_subdossier is really only used for documents,
    # while is_subdossier is only meaningful for dossiers.
    if IDossierMarker.providedBy(context):
        was_subdossier = IDossierMarker.providedBy(event.oldParent)
        is_subdossier = IDossierMarker.providedBy(event.newParent)
        if was_subdossier != is_subdossier:
            to_reindex.append('is_subdossier')

    if context.portal_type in TYPES_WITH_CONTAINING_SUBDOSSIER_INDEX:
        to_reindex.append('containing_subdossier')

    context.reindexObject(idxs=to_reindex)

    # synchronize with model if necessary
    if ITask.providedBy(context):
        sync_task(context, event)
Example #5
0
def isSubdossierIndexer(obj):
    # TODO: should be replaced with the is_subdossier method
    # from og.dossier.base.py
    parent = aq_parent(aq_inner(obj))
    if IDossierMarker.providedBy(parent):
        return True
    return False
Example #6
0
    def move_repository_reference_mappings(self, obj):
        intids = getUtility(IIntIds)
        annotations = IAnnotations(obj)

        if annotations and annotations.get(CHILD_REF_KEY):
            repository_mapping = PersistentDict(
                {CHILD_REF_KEY: {},
                 PREFIX_REF_KEY: {}})
            dossier_mapping = PersistentDict(
                {CHILD_REF_KEY: {},
                 PREFIX_REF_KEY: {}})

            for number, intid in annotations.get(CHILD_REF_KEY).items():
                try:
                    child = intids.getObject(intid)
                except KeyError:
                    # the object with this intid does not longer exist.
                    continue

                if IDossierMarker.providedBy(child):
                    dossier_mapping[CHILD_REF_KEY][number] = intid
                    dossier_mapping[PREFIX_REF_KEY][intid] = number
                else:
                    repository_mapping[CHILD_REF_KEY][number] = intid
                    repository_mapping[PREFIX_REF_KEY][intid] = number

            # save mapping
            annotations[REPOSITORY_FOLDER_KEY] = repository_mapping
            annotations[DOSSIER_KEY] = dossier_mapping

            # drop old mapings
            annotations.pop(CHILD_REF_KEY)
            annotations.pop(PREFIX_REF_KEY)
Example #7
0
    def _construct_object(self, container, item):
        portal_type = item['_type']
        fti = self._get_fti(portal_type)
        title_args = self._get_title_args(fti, item)

        with NoDossierReferenceNumbersIssued():
            # Create the object without automatically issuing a
            # reference number - we might want to set it explicitly
            obj = createContentInContainer(
                container, portal_type, **title_args)

            if IDossierMarker.providedBy(obj):
                prefix_adapter = IReferenceNumberPrefix(container)
                if not prefix_adapter.get_number(obj):
                    # Set the local reference number part for the
                    # dossier if provided in item, otherwise have
                    # the adapter issue the next one
                    local_refnum = item.get('reference_number')
                    if local_refnum is not None:
                        prefix_adapter.set_number(obj, local_refnum)
                    else:
                        prefix_adapter.set_number(obj)

        self._set_guid(obj, item)
        return obj
Example #8
0
    def is_locked(self, recursive=True):
        """Determine whether a dossier currently is resolve locked.

        By default also considers a subdossier locked if any of its parent
        dossiers have a lock on them.

        If recursive=False is given, only the current dossier is checked for
        a lock (cheaper, this is used to display the state in the byline).

        If a lock exists (somewhere) but is older than RESOLVE_LOCK_LIFETIME,
        it is considered expired and treated as if it wouldn't exist.
        """
        item = self.context

        while IDossierMarker.providedBy(item):

            lockinfo = self.get_lockinfo(item)
            if lockinfo is not None and not self.is_expired(lockinfo):
                self.log("%s is resolve locked via lock on %r" % (self.context, item))
                return True

            if not recursive:
                return False

            item = aq_parent(item)

        return False
Example #9
0
def get_containing_dossier(obj):
    while not IPloneSiteRoot.providedBy(obj):
        if IDossierMarker.providedBy(obj) or IInbox.providedBy(obj):
            return obj
        obj = aq_parent(aq_inner(obj))

    return None
Example #10
0
    def replace_interactive_user(self, principal):
        """Replaces interactive users in the principal.
        """

        if principal == 'responsible':
            # find the dossier
            dossier = self.context
            while not IDossierMarker.providedBy(dossier):
                if IPloneSiteRoot.providedBy(dossier):
                    raise ValueError('Could not find dossier')
                dossier = aq_parent(aq_inner(dossier))
            # get the responsible of the dossier
            wrapped_dossier = IDossier(dossier)
            return wrapped_dossier.responsible

        elif principal == 'current_user':
            # get the current user
            mtool = getToolByName(self.context, 'portal_membership')
            member = mtool.getAuthenticatedMember()
            if not member:
                raise Unauthorized()
            return member.getId()

        else:
            return principal
    def is_allowed(self):
        """Perform the necessary checks to determine whether pasting is
        allowed / possible on the current context.
        """
        # Check whether pasting is allowed at all for the container type
        if self.context.portal_type in self.disabled_types:
            return False

        # XXX implement me in a more object oriented manner, i.e. by
        # implementing `is_pasting_allowed` for all our content types.
        if IDossierMarker.providedBy(self.context):
            if not self.context.is_open():
                return False

        objs = Clipboard(self.request).get_objs()
        if not objs:
            # Clipboard empty
            return False

        # Check whether there's an object in the clipboard whose type
        # is not allowed to be added to the container
        for obj in objs:
            if obj.portal_type not in self.allowed_content_types:
                return False

        return self.validate_private_folder_pasting(objs)
Example #12
0
    def raise_invalid(self):
        if IDossierMarker.providedBy(self.context):
            mail_address = IEmailAddress(
                self.request).get_email_for_object(self.context)
        else:
            parent = aq_parent(aq_inner(self.context))
            mail_address = IEmailAddress(
                self.request).get_email_for_object(parent)

        # Remove widget value in order to disable that the widget renders
        # radio-buttons (nochange/remove/replace) once a file has been
        # uploaded.
        # This is a special case since we are an additional validator
        # for the file field that may block an otherwise valid file upload.
        # The widget does not expect this to happen though.
        if getattr(self.view.parentForm, '_nullify_file_on_error', False):
            self.widget.value = None

        raise Invalid(_(
            u'error_mail_upload',
            default=(u"It's not possible to add E-mails here, please "
            "send it to ${mailaddress} or drag it to the dossier "
            "(Dragn'n'Drop)."),
            mapping={'mailaddress': mail_address}
            ))
Example #13
0
    def allowedContentTypes(self, *args, **kwargs):
        types = super(
            DossierContainer, self).allowedContentTypes(*args, **kwargs)
        # calculate depth
        depth = 0
        obj = self
        while IDossierMarker.providedBy(obj):
            depth += 1
            obj = aq_parent(aq_inner(obj))
            if IPloneSiteRoot.providedBy(obj):
                break

        # the adapter decides
        def filter_type(fti):
            # first we try the more specific one ...
            decider = queryMultiAdapter((self.REQUEST, self, fti),
                                    IConstrainTypeDecider,
                                    name=fti.portal_type)
            if not decider:
                # .. then we try the more general one
                decider = queryMultiAdapter((self.REQUEST, self, fti),
                                        IConstrainTypeDecider)
            if decider:
                return decider.addable(depth)
            # if we don't have an adapter, we just allow it
            return True
        # filter
        return filter(filter_type, types)
Example #14
0
 def _add_descendants(self):
     objs = self.obj.objectValues()
     for obj in objs:
         if IDossierMarker.providedBy(obj):
             self.dossiers[obj.UID()] = Dossier(obj)
         elif IDocumentSchema.providedBy(obj):
             self.documents[obj.UID()] = Document(obj)
def check_dossier_nesting(portal, options):
    """Find all Dossiers that are nested 3 levels or more (sub-sub-dossiers).
    """
    catalog = getToolByName(portal, 'portal_catalog')
    dossiers = catalog(object_provides=IDossierMarker.__identifier__)

    for brain in dossiers:
        obj = brain.getObject()
        subdossiers = [c for c in obj.getChildNodes()
                       if IDossierMarker.providedBy(c)]

        for subdossier in subdossiers:
            if subdossier.get_subdossiers() != []:
                badly_nested_dossiers = [c for c in subdossier.getChildNodes()
                                         if IDossierMarker.providedBy(c)]
                print badly_nested_dossiers
Example #16
0
 def _add_descendants(self):
     objs = self.obj.objectValues()
     for obj in objs:
         if IDossierMarker.providedBy(obj):
             self.dossiers.append(Dossier(obj, self.path))
         elif IBaseDocument.providedBy(obj) and obj.get_file():
             self.documents.append(Document(obj, self.path))
Example #17
0
def get_redirect_url(context):
        """return the url where the editing_document view was called from
        It should be a document listing."""

        referer = context.REQUEST.environ.get('HTTP_REFERER')
        portal_url = '/'.join(context.portal_url().split('/')[:-1])
        if referer:
            obj_path = referer[len(portal_url):]
            try:
                obj = context.restrictedTraverse(obj_path)
            except KeyError:
                return  '%s#overview' % context.absolute_url()

            # redirect to right tabbedview-tab
            if ITask.providedBy(obj):
                return '%s#relateddocuments' % (obj.absolute_url())
            elif IPloneSiteRoot.providedBy(obj):
                return '%s#mydocuments' % (obj.absolute_url())
            elif IDossierMarker.providedBy(obj):
                return '%s#documents' % (obj.absolute_url())
            else:
                return obj.absolute_url()

        else:
            return  '%s#overview' % context.absolute_url()
Example #18
0
    def get_parent_dossier(self):
        parent = aq_parent(aq_inner(self))

        if IDossierMarker.providedBy(parent):
            return parent

        return None
Example #19
0
    def render(self):
        self.request.response.setHeader('Content-type', 'application/json')
        payloads = self.get_base_payloads()

        dossier_notifications = {}

        for payload in payloads:
            document = payload['document']
            parent_dossier = document.get_parent_dossier()

            if parent_dossier and IDossierMarker.providedBy(parent_dossier) and parent_dossier.is_open():
                payload['bcc'] = IEmailAddress(self.request).get_email_for_object(parent_dossier)

                parent_dossier_uuid = api.content.get_uuid(parent_dossier)

                if parent_dossier_uuid not in dossier_notifications:
                    dossier_notifications[parent_dossier_uuid] = []

                dossier_notifications[parent_dossier_uuid].append(document)

            payload['title'] = document.title_or_id()
            payload['content-type'] = document.get_file().contentType
            payload['download'] = document.get_download_view_name()
            payload['filename'] = document.get_filename()
            del payload['document']
            notify(FileAttachedToEmailEvent(document))

        for uuid, documents in dossier_notifications.iteritems():
            dossier = api.content.get(UID=uuid)
            notify(DossierAttachedToEmailEvent(dossier, documents))

        return json.dumps(payloads)
Example #20
0
 def label(self):
     if IDossierMarker.providedBy(self.context):
         return _(u'Add Subdossier')
     else:
         portal_type = self.portal_type
         fti = getUtility(IDexterityFTI, name=portal_type)
         type_name = fti.Title()
         return pd_mf(u"Add ${name}", mapping={'name': type_name})
Example #21
0
 def assert_valid_container_state(self):
     container = self.context
     if IDossierMarker.providedBy(container) and not container.is_open():
         msg = _(u'Can only move objects from open dossiers!')
         IStatusMessage(self.request).addStatusMessage(
             msg, type='error')
         self.request.RESPONSE.redirect(
             '%s#documents' % container.absolute_url())
Example #22
0
def top_dossier_title(obj):
    """return the tilte of the top containing dossier."""
    dossier_title = ''
    while not IPloneSiteRoot.providedBy(obj):
        if IDossierMarker.providedBy(
            obj) or obj.portal_type == 'opengever.inbox.inbox':
            dossier_title = obj.Title()
        obj = aq_parent(aq_inner(obj))
    return dossier_title
Example #23
0
    def handle_submit(self, action):
        data, errors = self.extractData()
        if len(errors) == 0:

            source = data['request_paths'].split(';;')
            destination = data['destination_folder']
            failed_objects = []
            failed_resource_locked_objects = []
            copied_items = 0

            for path in source:

                # Get source object
                src_object = self.context.unrestrictedTraverse(
                    path.encode('utf-8'))

                # Get parent object
                source_container = aq_parent(aq_inner(
                    self.context.unrestrictedTraverse(
                        path.encode('utf-8'))))

                src_name = src_object.title
                src_id = src_object.id

                # If parent isn't a dossier and obj is a document
                # it's connected to a task and shouldn't be moved
                if not IDossierMarker.providedBy(source_container) and \
                    IDocumentSchema.providedBy(src_object):
                    msg = _(u'Document ${name} is connected to a Task.\
                    Please move the Task.', mapping=dict(name=src_name))
                    IStatusMessage(self.request).addStatusMessage(
                        msg, type='error')
                    continue

                try:
                    # Try to cut and paste object
                    clipboard = source_container.manage_cutObjects(src_id)
                    destination.manage_pasteObjects(clipboard)
                    copied_items += 1

                except ResourceLockedError:
                    # The object is locket over webdav
                    failed_resource_locked_objects.append(src_name)
                    continue

                except (ValueError, CopyError):
                    # Catch exception and add title to a list of failed objects
                    failed_objects.append(src_name)
                    continue

            self.create_statusmessages(
                copied_items,
                failed_objects,
                failed_resource_locked_objects, )

            self.request.RESPONSE.redirect(destination.absolute_url())
Example #24
0
    def find_dossier(self):
        obj = self.context

        while not IPloneSiteRoot.providedBy(obj):
            if IDossierMarker.providedBy(obj):
                return obj
            else:
                obj = aq_parent(aq_inner(obj))

        return None
Example #25
0
 def _get_dossier_depth(self):
     # calculate depth
     depth = 0
     obj = self
     while IDossierMarker.providedBy(obj):
         depth += 1
         obj = aq_parent(aq_inner(obj))
         if IPloneSiteRoot.providedBy(obj):
             break
     return depth
Example #26
0
 def available(self):
     if not self.enabled():
         return False
     if IDossierMarker.providedBy(self.context):
         return True
     if not IRepositoryFolder.providedBy(self.context):
         return False
     if self.context.is_leaf_node():
         return True
     return False
    def find_parent_dossier(self):
        """Returns the first parent dossier relative to the current context.
        """

        obj = self.context
        while not IDossierMarker.providedBy(obj):
            obj = aq_parent(aq_inner(obj))

            if IPloneSiteRoot.providedBy(obj):
                return ValueError('Site root reached while searching '
                                  'parent dossier.')

        return obj
Example #28
0
def reindex_containing_dossier(dossier, event):
    """Reindex the containging_dossier index for all the contained obects,
    when the title has changed."""
    if not IDossierMarker.providedBy(aq_parent(aq_inner(dossier))):
        for descr in event.descriptions:
            for attr in descr.attributes:
                if attr == "IOpenGeverBase.title":
                    for brain in dossier.portal_catalog(path="/".join(dossier.getPhysicalPath())):

                        brain.getObject().reindexObject(idxs=["containing_dossier"])

                        if brain.portal_type in ["opengever.task.task", "opengever.inbox.forwarding"]:
                            sync_task(brain.getObject(), event)
Example #29
0
def get_main_dossier(obj):
    """Helper method which returns the main dossier (or inbox) of the given
    object.
    If the given object is not storred inside a dossier it returns None."""

    dossier = None
    while not IPloneSiteRoot.providedBy(obj):
        if IDossierMarker.providedBy(obj) or IInbox.providedBy(obj):
            dossier = obj

        obj = aq_parent(aq_inner(obj))

    return dossier
Example #30
0
def find_parent_dossier(content):
    """Returns the first parent dossier relative to the current context.
    """

    if IPloneSiteRoot.providedBy(content):
        raise ValueError('Site root passed as argument.')

    while content and not IDossierMarker.providedBy(content):
        content = aq_parent(aq_inner(content))
        if IPloneSiteRoot.providedBy(content):
            raise ValueError('Site root reached while searching '
                             'parent dossier.')
    return content