Example #1
0
def handleCancelCheckout(event):
    lockable = ILockable(event.object)
    if lockable.locked():
        # unlock working copy if it was auto-locked, or this will fail
        lockable.clear_locks()
    lock.unlockContext(event.baseline)
    event.baseline.reindexObject(idxs=['review_state'])
def delete_unwanted_objects_from_memberfolder(portal,memberfolder,logger):
    ct = getToolByName(portal,'portal_catalog')    
    strURL = "/".join(memberfolder.getPhysicalPath())
    query = {'path':{'query':strURL},'portal_type':('Space','RecycleBin')}
    objMemSpaces = [b.getObject() for b in ct(query)]
    
    for o in objMemSpaces:
        
        if callable(o.id):
            o_id = o.id()
        else:
            o_id = o.id        
        try:
                
            from plone.locking.interfaces import ILockable
            lockable = ILockable(o)
            was_locked = False
            if lockable.locked():
                was_locked = True
                lockable.unlock()
              
            parentItem = o.getParentNode()
            parentItem.manage_delObjects(ids=[o_id])   
            
            transaction.savepoint()
        except ComponentLookupError:
            pass
        
        logger.info("Deleted %s object from %s member folder." % (o_id, memberfolder.getId(),))
        transaction.savepoint()
    def test_lockinfo_tile(self):
        self.other_browser.open(
            self.pageURL +
            '/@@plone.app.standardtiles.lockinfo'
        )

        self.assertIn('plone-lock-status', self.other_browser.contents)

        root = fromstring(self.other_browser.contents)
        nodes = root.xpath('//body//*[@id="plone-lock-status"]')
        self.assertEqual(len(nodes), 1)
        self.assertEqual(0, len(nodes[0].getchildren()))

        # Then lock the page:
        lockable = ILockable(self.page)
        lockable.lock()
        transaction.commit()

        # The tile will show them:
        self.other_browser.open(
            self.pageURL +
            '/@@plone.app.standardtiles.lockinfo'
        )

        self.assertIn('plone-lock-status', self.other_browser.contents)

        root = fromstring(self.other_browser.contents)
        nodes = root.xpath('//body//*[@id="plone-lock-status"]')
        self.assertEqual(len(nodes), 1)
        self.assertGreaterEqual(len(nodes[0].getchildren()), 1)
Example #4
0
    def test_decide_agenda_item_creates_locked_excerpt_in_dossier(self, browser):
        self.setup_excerpt_template()
        proposal = self.setup_proposal()
        # schedule
        view = 'unscheduled_proposals/{}/schedule'.format(
            proposal.load_model().proposal_id)

        browser.login().open(self.meeting_wrapper, view=view)
        agenda_item = AgendaItem.query.first()
        browser.login().open(
            self.meeting_wrapper,
            view='agenda_items/{}/decide'.format(agenda_item.agenda_item_id),
            data={'_authenticator': createToken()})

        agenda_item = AgendaItem.query.first()  # refresh
        proposal = agenda_item.proposal
        excerpt_in_dossier = proposal.excerpt_document.resolve_document()
        lockable = ILockable(excerpt_in_dossier)
        self.assertTrue(lockable.locked())
        self.assertTrue(lockable.can_safely_unlock(MEETING_EXCERPT_LOCK))

        browser.open(excerpt_in_dossier)
        self.assertEqual(u'This document is a copy of the excerpt Fooo - '
                         u'C\xf6mmunity meeting from the meeting C\xf6mmunity '
                         u'meeting and cannot be edited directly.',
                         info_messages()[0])
        message_links = browser.css('.portalMessage.info a')
        self.assertEqual(
            'http://nohost/plone/opengever-meeting-committeecontainer/committee-1/submitted-proposal-1/document-3',
            message_links[0].get('href'))
        self.assertEqual(
            'http://nohost/plone/opengever-meeting-committeecontainer/committee-1/meeting-1/view',
            message_links[1].get('href'))
Example #5
0
    def test_submit_additional_document_creates_new_locked_document(self):
        committee = create(Builder('committee').titled('My committee'))
        document = create(Builder('document')
                          .within(self.dossier)
                          .titled(u'A Document')
                          .with_dummy_content())
        proposal = create(Builder('proposal')
                          .within(self.dossier)
                          .titled(u'My Proposal')
                          .as_submitted()
                          .having(committee=committee.load_model()))

        proposal.submit_additional_document(document)
        submitted_proposal = api.portal.get().restrictedTraverse(
            proposal.load_model().submitted_physical_path.encode('utf-8'))
        docs = submitted_proposal.listFolderContents()
        self.assertEqual(1, len(docs))
        submitted_document = docs.pop()

        self.assertEqual(document.Title(), submitted_document.Title())
        self.assertEqual(document.file.filename,
                         submitted_document.file.filename)

        # submitted document should be locked by custom lock
        lockable = ILockable(submitted_document)
        self.assertTrue(lockable.locked())
        self.assertTrue(lockable.can_safely_unlock(MEETING_SUBMITTED_LOCK))

        self.assertSubmittedDocumentCreated(proposal, document, submitted_document)
    def test_locked_is_false_if_lock_is_invalid(self):
        create(Builder('lock')
               .of_obj(self.wrapper)
               .having(time=utcnow_tz_aware() - timedelta(seconds=800)))

        lockable = ILockable(self.wrapper)
        self.assertFalse(lockable.locked())
Example #7
0
    def migrate(self, unittest=0):
        """Migrates the object
        """
        beforeChange, afterChange = self.getMigrationMethods()

        lockable = ILockable(self.old, None)
        if lockable and lockable.locked():
            lockable.unlock()

        for method in beforeChange:
            __traceback_info__ = (self, method, self.old, self.orig_id)
            # may raise an exception, catch it later
            method()
        # preserve position on rename
        self.need_order = IOrderedContainer.providedBy(self.parent)
        if self.need_order:
            self._position = self.parent.getObjectPosition(self.orig_id)
        self.renameOld()
        self.createNew()

        for method in afterChange:
            __traceback_info__ = (self, method, self.old, self.orig_id)
            # may raise an exception, catch it later
            method()

        self.reorder()
        self.remove()
Example #8
0
    def is_locked_by_another_user(self):
        """Return False if the document is locked by the current user or is
        not locked at all, True otherwise.

        """
        lockable = ILockable(self.context)
        return not lockable.can_safely_unlock()
Example #9
0
 def safe_unlock(self, redirect=True):
     """Unlock the object if the current user has the lock
     """
     lockable = ILockable(self.context)
     if lockable.can_safely_unlock():
         lockable.unlock()
     if redirect:
         self.redirect()
Example #10
0
 def test_lockinfo_is_visible_for_lock_owner(self, browser):
     self.login(self.regular_user, browser=browser)
     browser.open(self.document)
     self.assertEquals([], info_messages())
     lockable = ILockable(self.document)
     lockable.lock()
     browser.open(self.document)
     self.assertEquals([self.lock_message], info_messages())
Example #11
0
    def is_available_for_current_user(self):
        """Check whether the current meeting can be safely unlocked.

        This means the current meeting is not locked by another user.
        """

        lockable = ILockable(self.context)
        return lockable.can_safely_unlock()
Example #12
0
 def testLockedItem(self):
     membership_tool = getToolByName(self.folder, 'portal_membership')
     membership_tool.addMember('anotherMember', 'secret', ['Member'], [])
     locking = ILockable(self.folder.doc1)
     locking.lock()
     self.login('anotherMember')
     actions = self.menu.getMenuItems(self.folder.doc1, self.request)
     self.assertEqual(len(actions), 0)
Example #13
0
 def is_locked_for_current_user(self):
     """True if this object is locked for the current user (i.e. the
     current user is not the lock owner)
     """
     lockable = ILockable(aq_inner(self.context))
     # Faster version - we rely on the fact that can_safely_unlock() is
     # True even if the object is not locked
     return not lockable.can_safely_unlock()
Example #14
0
 def test_unlock_button_is_visible_for_manager(self, browser):
     self.login(self.regular_user, browser=browser)
     browser.open(self.document)
     self.assertEquals([], info_messages())
     lockable = ILockable(self.document)
     lockable.lock()
     self.login(self.manager, browser=browser)
     browser.open(self.document)
     self.assertEquals([self.lock_message + self.unlock_message], info_messages())
Example #15
0
    def test_refresh_locks_update_locks_to_current_time(self):
        lockable = ILockable(self.wrapper)
        lockable.lock()

        with freeze(pytz.UTC.localize(datetime(2015, 03, 10, 12, 05))):
            lockable.refresh_lock()

            lock = Lock.query.one()
            self.assertEqual(
                pytz.UTC.localize(datetime(2015, 03, 10, 12, 05)), lock.time)
Example #16
0
    def force_unlock(self, redirect=True):
        """Steal the lock.

        If redirect is True, redirect back to the context URL, i.e. reload
        the page.
        """
        lockable = ILockable(self.context)
        lockable.unlock()
        if redirect:
            self.redirect()
Example #17
0
    def force_unlock(self, redirect=True):
        """Steal the lock.

        If redirect is True, redirect back to the context URL, i.e. reload
        the page.
        """
        lockable = ILockable(self.context)
        lockable.unlock()
        if redirect:
            self.request.RESPONSE.redirect(self.context.absolute_url())
Example #18
0
    def step1andstep2(self):
        """Explore the site's content searching for misplaced content and move
        it to its nearest translated parent.
        """
        portal = getSite()

        output = []
        # Step 1 - Audit the content tree and make a list with the candidates
        # to be moved to the right RLF. Once we get a candidate, decide if it
        # should be moved to its nearest parent with the same language. Trying
        # to avoid the catalog in order to avoid problems with big sites and
        # bad or corrupted catalogs.
        self.content_tree = []
        self.findContent(portal, 0)
        logger.info("Step 1: Eligible content: %s" % self.content_tree)

        # We now have a list of lists that maps each eligible content with its
        # depth in the content tree

        # Step 2 - Move the eligible content to its nearest translated parent
        # from the most deepest located content to the outer ones
        self.content_tree.reverse()

        for depth in self.content_tree:
            if depth != []:
                for content in depth:
                    parent = aq_parent(content)
                    target_folder = self.searchNearestTranslatedParent(content)
                    # Test if the id already exist previously

                    try:
                        cutted = parent.manage_cutObjects(content.getId())
                    except ResourceLockedError:
                        lockable = ILockable(content)
                        lockable.unlock()
                        cutted = parent.manage_cutObjects(content.getId())
                    try:
                        target_folder.manage_pasteObjects(cutted)
                        info_str = "Step 2: Moved object %s to folder %s" % (
                                   '/'.join(content.getPhysicalPath()),
                                   '/'.join(target_folder.getPhysicalPath()))
                        log = logger.info
                    except Exception as err:
                        info_str = "ERROR. Step 2: not possible to move " \
                            "object %s to folder %s. Error: %s" % (
                                '/'.join(content.getPhysicalPath()),
                                '/'.join(target_folder.getPhysicalPath()),
                                err)
                        log = logger.error
                    log(info_str)
                    output.append(info_str)

        logger.info('Finished step 2')
        return output
Example #19
0
    def begin(self, formname, fieldname, structure='false'):
        """Begin inline editing - find the widget for the given field name
        in the given form (looked up as a view on the context), then hide the
        block with the id '${fieldname}-display' and display an edit form in
        its place. If 'structure' is 'true' (a string), then the inline 
        editable field will eventually permit HTML input to be rendered
        unescaped.
        """
        context = aq_inner(self.context)
        request = aq_inner(self.request)
        
        form = getMultiAdapter((context, request), name=formname)
        form = form.__of__(context)
        
        if fieldname.startswith(form.prefix):
            fieldname = fieldname[len(form.prefix)+1:]
            
        formlib_field = form.form_fields[fieldname]
        widgets = formlib.setUpEditWidgets((formlib_field,), form.prefix, 
            context, request, ignore_request=True)
            
        widget = widgets[fieldname]
        
        display_id = '%s-display' % fieldname
        form_id = '%s-form' % fieldname
        
        ksscore = self.getCommandSet('core')
        zopecommands = self.getCommandSet('zope')
        plonecommands = self.getCommandSet('plone')
        
        # lock the context (or issue warning)
        locking = ILockable(context, None)
        if locking:
            if not locking.can_safely_unlock():
                selector = ksscore.getHtmlIdSelector('plone-lock-status')
                zopecommands.refreshViewlet(selector, 'plone.abovecontent', 'plone.lockinfo')
                plonecommands.refreshContentMenu()
                return
            else: # we are locking the content
                locking.lock()
        
        plonecommands.issuePortalMessage('')
        
        # hide the existing display field
        display_selector = ksscore.getHtmlIdSelector(display_id)
        ksscore.addClass(display_selector, 'hiddenStructure')
        
        # show the form
        form_html = self.form_template(widget=widget,
                                       form_id=form_id,
                                       fieldname=fieldname,
                                       structure=structure)

        ksscore.insertHTMLAfter(display_selector, form_html)
Example #20
0
    def step1andstep2(self):
        """Explore the site's content searching for misplaced content and move
        it to its nearest translated parent.
        """
        portal = getSite()

        output = []
        # Step 1 - Audit the content tree and make a list with the candidates
        # to be moved to the right RLF. Once we get a candidate, decide if it
        # should be moved to its nearest parent with the same language. Trying
        # to avoid the catalog in order to avoid problems with big sites and
        # bad or corrupted catalogs.
        self.content_tree = []
        self.findContent(portal, 0)
        logger.info("Step 1: Eligible content: %s" % self.content_tree)

        # We now have a list of lists that maps each eligible content with its
        # depth in the content tree

        # Step 2 - Move the eligible content to its nearest translated parent
        # from the most deepest located content to the outer ones
        self.content_tree.reverse()

        for depth in self.content_tree:
            if depth != []:
                for content in depth:
                    parent = aq_parent(content)
                    target_folder = self.searchNearestTranslatedParent(content)
                    # Test if the id already exist previously

                    try:
                        cutted = parent.manage_cutObjects(content.getId())
                    except ResourceLockedError:
                        lockable = ILockable(content)
                        lockable.unlock()
                        cutted = parent.manage_cutObjects(content.getId())
                    try:
                        target_folder.manage_pasteObjects(cutted)
                        info_str = "Step 2: Moved object %s to folder %s" % (
                            '/'.join(content.getPhysicalPath()), '/'.join(
                                target_folder.getPhysicalPath()))
                        log = logger.info
                    except Exception as err:
                        info_str = "ERROR. Step 2: not possible to move " \
                            "object %s to folder %s. Error: %s" % (
                                '/'.join(content.getPhysicalPath()),
                                '/'.join(target_folder.getPhysicalPath()),
                                err)
                        log = logger.error
                    log(info_str)
                    output.append(info_str)

        logger.info('Finished step 2')
        return output
Example #21
0
    def step3(self):
        """Move the existing site content to its correspondent RLF.
        """
        portal = getSite()
        pc = getToolByName(portal, "portal_catalog")
        pl = getToolByName(portal, "portal_languages")

        supported_langs = pl.getSupportedLanguages()

        output = []
        # Step 3: Move all the remaining content to its correspondent RLFs
        for lang in supported_langs:
            RLF_id = "%s" % lang
            folder = getattr(portal, RLF_id, None)
            if not folder:
                raise AttributeError("One of the root language folder are \
                                      missing. Check the site's language \
                                      setup.")

            path = '/'.join(portal.getPhysicalPath())
            objects = pc.searchResults(path={
                'query': path,
                'depth': 1
            },
                                       sort_on='getObjPositionInParent',
                                       Language=lang)

            for brain in objects:
                if brain.id != lang:
                    old_path = brain.getPath()

                    try:
                        cutted = self.context.manage_cutObjects(brain.id)
                    except ResourceLockedError:
                        content = brain.getObject()
                        lockable = ILockable(content)
                        lockable.unlock()
                        cutted = self.context.manage_cutObjects(brain.id)
                    try:
                        folder.manage_pasteObjects(cutted)
                        info_str = "Moved object %s to language root folder "\
                            "%s" % (old_path, lang)
                        log = logger.info
                    except Exception as err:
                        info_str = "ERROR. Step 3: not possible to move "\
                            "object %s to root language folder %s. Error: %s"\
                            % (old_path, lang, err)
                        log = logger.error
                    log(info_str)
                    output.append(info_str)

        logger.info('Finished step 3')
        return output
 def unlockPerson(self):
     obj = self.context.aq_inner
     try:
         from plone.locking.interfaces import ILockable
         HAS_LOCKING = True
     except ImportError:
         HAS_LOCKING = False
     if HAS_LOCKING:
         lockable = ILockable(obj)
         if lockable.locked():
             lockable.unlock()
     return self.render()
Example #23
0
 def testLockedItem(self):
     if self.is_dx:
         # dexterity has no locking ootb
         # see https://github.com/plone/plone.app.contenttypes/issues/140
         return
     membership_tool = getToolByName(self.folder, 'portal_membership')
     membership_tool.addMember('anotherMember', 'secret', ['Member'], [])
     locking = ILockable(self.folder.doc1)
     locking.lock()
     login(self.portal, 'anotherMember')
     actions = self.menu.getMenuItems(self.folder.doc1, self.request)
     self.assertEqual(len(actions), 0)
Example #24
0
    def test_protocol_document_is_unlocked_when_meeting_is_closed(self, browser):
        self.setup_generated_protocol(browser)

        browser.find('Close meeting').click()

        browser.open(self.meeting.get_url())

        browser.find('Protocol-My meeting').click()
        document = browser.context
        lockable = ILockable(document)

        self.assertFalse(lockable.locked())
Example #25
0
 def test_update_locked_object_with_token_succeeds(self):
     lockable = ILockable(self.doc)
     lockable.lock()
     transaction.commit()
     response = self.api_session.patch(
         "/",
         headers={"Lock-Token": lockable.lock_info()[0]["token"]},
         json={"title": "New Title"},
     )
     transaction.commit()
     self.assertEqual(response.status_code, 204)
     self.assertEqual(self.doc.Title(), "New Title")
 def unlockPerson(self):
     obj = self.context.aq_inner
     try:
         from plone.locking.interfaces import ILockable
         HAS_LOCKING = True
     except ImportError:
         HAS_LOCKING = False
     if HAS_LOCKING:
         lockable = ILockable(obj)
         if lockable.locked():
             lockable.unlock()
     return self.render()
Example #27
0
 def testLockedItem(self):
     if self.is_dx:
         # dexterity has no locking ootb
         # see https://github.com/plone/plone.app.contenttypes/issues/140
         return
     membership_tool = getToolByName(self.folder, 'portal_membership')
     membership_tool.addMember('anotherMember', 'secret', ['Member'], [])
     locking = ILockable(self.folder.doc1)
     locking.lock()
     login(self.portal, 'anotherMember')
     actions = self.menu.getMenuItems(self.folder.doc1, self.request)
     self.assertEqual(len(actions), 0)
Example #28
0
    def test_protocol_document_is_unlocked_when_meeting_is_closed(
            self, browser):
        self.setup_generated_protocol(browser)

        browser.find('Close meeting').click()

        browser.open(self.meeting.get_url())

        browser.find('Protocol-My meeting').click()
        document = browser.context
        lockable = ILockable(document)

        self.assertFalse(lockable.locked())
Example #29
0
    def action(self, obj):
        parent = obj.aq_inner.aq_parent

        lockable = ILockable(obj, None)
        if lockable and lockable.locked():
            lockable.clear_locks()

        try:
            parent.manage_delObjects(obj.getId(), self.request)
        except Unauthorized:
            self.errors.append(
                _(u'You are not authorized to delete ${title}.',
                  mapping={u'title': self.objectTitle(self.dest)}))
Example #30
0
    def test_protocol_document_is_locked_by_system_once_generated(self, browser):
        self.setup_generated_protocol(browser)

        browser.find('Protocol-My meeting').click()
        document = browser.context
        lockable = ILockable(document)

        self.assertTrue(lockable.locked())
        self.assertTrue(lockable.can_safely_unlock(SYS_LOCK))
        self.assertFalse(lockable.can_safely_unlock(STEALABLE_LOCK))

        lock_info = lockable.lock_info()[0]
        self.assertEqual(u'sys.lock', lock_info['type'].__name__)
    def test_atct_not_lockable(self):
        portal = self.layer['portal']
        setRoles(portal, TEST_USER_ID, ['Contributor'])
        portal.invokeFactory('Document', 'adoc',
            title='A title',
            description='Some description',
            text='Some text')
        doc = portal['adoc']

        lockable = ILockable(doc)
        self.assertEqual(False, lockable.locked())
        lockable.lock()
        self.assertEqual(False, lockable.locked())
    def test_force_unlock_clears_lock(self, browser):
        self.login(self.regular_user, browser)
        oc_url = self.fetch_document_checkout_oc_url(browser, self.document)
        tokens = self.validate_checkout_token(self.regular_user, oc_url,
                                              self.document)
        lockable = ILockable(self.document)

        self.lock_document(browser, tokens, self.document)
        self.assertTrue(lockable.locked())

        self.login(self.manager, browser)
        browser.open(self.document)
        browser.click_on("Unlock")
        self.assertFalse(lockable.locked())
Example #33
0
    def step3(self):
        """Move the existing site content to its correspondent RLF.
        """
        portal = getSite()
        pc = getToolByName(portal, "portal_catalog")
        pl = getToolByName(portal, "portal_languages")

        supported_langs = pl.getSupportedLanguages()

        output = []
        # Step 3: Move all the remaining content to its correspondent RLFs
        for lang in supported_langs:
            RLF_id = "%s" % lang
            folder = getattr(portal, RLF_id, None)
            if not folder:
                raise AttributeError("One of the root language folder are \
                                      missing. Check the site's language \
                                      setup.")

            path = '/'.join(portal.getPhysicalPath())
            objects = pc.searchResults(path={'query': path, 'depth': 1},
                                       sort_on='getObjPositionInParent',
                                       Language=lang)

            for brain in objects:
                if brain.id != lang:
                    old_path = brain.getPath()

                    try:
                        cutted = self.context.manage_cutObjects(brain.id)
                    except ResourceLockedError:
                        content = brain.getObject()
                        lockable = ILockable(content)
                        lockable.unlock()
                        cutted = self.context.manage_cutObjects(brain.id)
                    try:
                        folder.manage_pasteObjects(cutted)
                        info_str = "Moved object %s to language root folder "\
                            "%s" % (old_path, lang)
                        log = logger.info
                    except Exception as err:
                        info_str = "ERROR. Step 3: not possible to move "\
                            "object %s to root language folder %s. Error: %s"\
                            % (old_path, lang, err)
                        log = logger.error
                    log(info_str)
                    output.append(info_str)

        logger.info('Finished step 3')
        return output
def remove_spacesobject_fromsite(portal,logger):
    from plone.app.linkintegrity.interfaces import ILinkIntegrityNotificationException
    portal_properties=getToolByName(portal, 'portal_properties')
    is_link_integrity = portal_properties.site_properties.enable_link_integrity_checks
    if is_link_integrity:
        portal_properties.site_properties.manage_changeProperties(enable_link_integrity_checks=False)
    
    spaces = None
    try:
        spaces = getToolByName(portal,'spaces')
        if spaces.portal_type != 'SpacesFolder':
            spaces = None
    except AttributeError:
        pass
    
    spacesid = 'spaces'
    
    try:
        if spaces <> None:
            if callable(spaces.id):
                o_id = spaces.id()
            else:
                o_id = spaces.id
            
            spacesid = o_id
            
            from plone.locking.interfaces import ILockable
            lockable = ILockable(spaces)
            was_locked = False
            if lockable.locked():
                was_locked = True
                lockable.unlock()
            
            portal.manage_delObjects(ids=[o_id])
            logger.info("Deleted spaces object from site.")
            transaction.savepoint()
    except ILinkIntegrityNotificationException:
        pass
        
    recyclebin = getToolByName(portal,'recyclebin')
    
    if recyclebin <> None:
        
        try:
            objspaces = getattr(portal,spacesid)
            if objspaces.portal_type == 'SpacesFolder':
                from plone.locking.interfaces import ILockable
                lockable = ILockable(objspaces)
                was_locked = False
                if lockable.locked():
                    was_locked = True
                    lockable.unlock()
                
                recyclebin.manage_delObjects(ids=[spacesid])
                logger.info("Deleting spaces object from global recyclebin.")
        except AttributeError:
            pass
        
    if is_link_integrity:
        portal_properties.site_properties.manage_changeProperties(enable_link_integrity_checks=True)
Example #35
0
    def test_clear_locks_remove_all_locks_on_the_object(self):
        lockable = ILockable(self.wrapper)
        lockable.lock()
        self.assertTrue(lockable.locked())

        lockable.clear_locks()
        self.assertFalse(lockable.locked())
Example #36
0
def is_locked(obj, request):
    """Returns true if the object is locked and the request doesn't contain
    the lock token.
    """
    lockable = ILockable(obj, None)
    if lockable is None:
        return False
    if lockable.locked():
        token = request.getHeader("Lock-Token", "")
        lock_info = lockable.lock_info()
        if len(lock_info) > 0 and lock_info[0]["token"] == token:
            return False
        return True
    return False
Example #37
0
    def reply(self):
        lockable = ILockable(self.context)
        if lockable.can_safely_unlock():
            lockable.unlock()

            if INonStealableLock.providedBy(self.context):
                noLongerProvides(self.context, INonStealableLock)

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

        return lock_info(self.context)
Example #38
0
    def test_can_safely_unlock_is_true_if_a_lock_of_the_current_user_exists(
            self):
        lock = create(
            Builder('lock').of_obj(
                self.wrapper).having(lock_type=u'plone.locking.stealable'))

        self.assertTrue(ILockable(self.wrapper).can_safely_unlock())
Example #39
0
    def test_lock_info_returns_an_list_of_dicts_of_all_valid_locks(self):
        # valid
        lock1 = create(Builder('lock')
                      .of_obj(self.wrapper)
                      .having(time=utcnow_tz_aware() - timedelta(seconds=100)))

        self.assertEquals(
            [{'creator': TEST_USER_ID,
              'time': lock1.time,
              'token': 'Meeting:1',
              'type': STEALABLE_LOCK}],
            ILockable(self.wrapper).lock_info())

        # invalid
        lock1.time = utcnow_tz_aware() - timedelta(seconds=800)
        self.assertEquals([], ILockable(self.wrapper).lock_info())
    def test_delete_confirmation_if_locked(self):
        folder = self.portal['f1']
        lockable = ILockable.providedBy(folder)

        form = getMultiAdapter(
            (folder, self.request), name='delete_confirmation')
        form.update()

        self.assertFalse(form.is_locked)

        if lockable:
            lockable.lock()

        form = getMultiAdapter(
            (folder, self.request), name='delete_confirmation')
        form.update()

        self.assertFalse(form.is_locked)

        # After switching the user it should not be possible to delete the
        # object. Of course this is only possible if our context provides
        # ILockable interface.
        if lockable:
            logout()
            login(self.portal, 'editor')

            form = getMultiAdapter(
                (folder, self.request), name='delete_confirmation')
            form.update()
            self.assertTrue(form.is_locked)

            logout()
            login(self.portal, TEST_USER_NAME)

            ILockable(folder).unlock()
Example #41
0
    def do_action(self):
        if is_locked(self):
            # force unlock before delete...
            lockable = ILockable(self.context)
            lockable.clear_locks()

        try:
            self.parent.manage_cutObjects(self.context.getId(), self.request)
        except CopyError:
            return self.do_redirect(
                self.view_url,
                _(u'${title} is not moveable.', mapping={'title': self.title}))

        return self.do_redirect(
            self.view_url, _(u'${title} cut.', mapping={'title': self.title}),
            'info')
Example #42
0
 def test_is_locked(self):
     self.assertEquals(self.dview.is_locked(), False)
     ILockable(self.folder.d1).lock()
     self.logout(
     )  # The object is not "locked" if it was locked by the current user
     del self.app.REQUEST.__annotations__
     self.assertEquals(self.dview.is_locked(), True)
Example #43
0
    def test_logged_in_locked_icon_is_locked(self):
        viewlet = self._get_viewlet()
        ILockable(self.context).lock()
        lockIconUrl = '<img src="http://nohost/plone/lock_icon.png" alt="" \
title="Locked" height="16" width="16" />'

        self.assertEqual(viewlet.locked_icon(), lockIconUrl)
Example #44
0
    def kss_obj_delete(self, selector='.kssDeletionRegion'):

        obj = self.context.aq_inner
        if obj.getPortalTypeName() == 'Discussion Item':
            parent = obj.inReplyTo()
            if parent is not None:
                portal_discussion = getUtility(IDiscussionTool)
                talkback = portal_discussion.getDiscussionFor(parent)
            else:
                talkback = obj.aq_parent

            # remove the discussion item
            talkback.deleteReply(str(obj.getId()))

        else:
            # 被锁定时先解锁
            if HAS_LOCKING:
                lockable = ILockable(obj)
                if lockable.locked():
                    lockable.unlock()

            parent = obj.aq_parent
            # archetypes的manage_delObjects会检查每个item的删除权限
            originalSecurityManager = SecurityManagement.getSecurityManager()
            SecurityManagement.newSecurityManager(
                None, User.SimpleUser('admin', '', ('Manager', ), ''))
            parent.manage_delObjects(str(obj.getId()))
            SecurityManagement.setSecurityManager(originalSecurityManager)

        if selector.startswith('redirect2'):
            # 跳转到某个地址
            # 需要定义 # class="kssattr-delSelector-redirect2http://test.everydo.com"
            redirect2url = selector[len('redirect2'):]
            self.getCommandSet('zopen').redirect(url=redirect2url)
        else:
            core = self.getCommandSet('core')
            effects = self.getCommandSet('effects')
            selector = core.getParentNodeSelector(selector)
            # effects.effect(selector, 'fade')

            core.deleteNode(selector)

        self.getCommandSet('plone').issuePortalMessage(
            translate(_(u'Deleted.'), default="Deleted.",
                      context=self.request),
            translate(_(u'Info'), default="Info", context=self.request))
        return self.render()
    def xmChangeWorkflowState(self, uid, url):
        """Change the workflow state, currently only of a Task."""
        context = aq_inner(self.context)
        ksscore = self.getCommandSet('core')
        zopecommands = self.getCommandSet('zope')
        plonecommands = self.getCommandSet('plone')

        locking = ILockable(context, None)
        if locking is not None and not locking.can_safely_unlock():
            selector = ksscore.getHtmlIdSelector('plone-lock-status')
            zopecommands.refreshViewlet(selector, 'plone.abovecontent',
                                        'plone.lockinfo')
            plonecommands.refreshContentMenu()
            return self.render()

        (proto, host, path, query, anchor) = urlsplit(url)
        if not path.endswith('content_status_modify'):
            raise KSSExplicitError('only content_status_modify is handled')
        action = query.split("workflow_action=")[-1].split('&')[0]
        uid_catalog = getToolByName(context, 'uid_catalog')
        brain = uid_catalog(UID=uid)[0]
        obj = brain.getObject()
        # This may give a UnicodeDecodeError if the title has
        # non-ascii characters:
        # obj.content_status_modify(action)
        # So we do it manually, which is better anyway:
        wftool = getToolByName(context, 'portal_workflow')
        wftool.doActionFor(obj, action=action)
        if IXMStory.providedBy(self.context):
            # Only refresh content if the context is a Story,
            # otherwise you get too much tasks listed.
            selector = ksscore.getCssSelector('.contentViews')
            zopecommands.refreshViewlet(selector, 'plone.contentviews',
                                        'plone.contentviews')
            zopecommands.refreshProvider('.tasklist_table',
                                         'xm.tasklist.simple')
            plonecommands.refreshContentMenu()
        else:
            # In all other cases, we can at least refresh the part
            # that shows the workflow info for this item.
            wf_change = obj.restrictedTraverse('xm_workflow_change')
            html = wf_change()
            selector = ksscore.getHtmlIdSelector('id-%s' % uid)
            ksscore.replaceHTML(selector, html)
        self.issueAllPortalMessages()
        self.cancelRedirect()
Example #46
0
def lock_info(obj):
    """Returns lock information about the given object."""
    lockable = ILockable(obj, None)
    if lockable is not None:
        info = {"locked": lockable.locked(), "stealable": lockable.stealable()}
        lock_info = lockable.lock_info()
        if len(lock_info) > 0:
            info["creator"] = lock_info[0]["creator"]
            info["time"] = lock_info[0]["time"]
            info["token"] = lock_info[0]["token"]
            lock_type = lock_info[0]["type"]
            if lock_type:
                info["name"] = lock_info[0]["type"].__name__
            lock_item = webdav_lock(obj)
            if lock_item:
                info["timeout"] = lock_item.getTimeout()
        return info
Example #47
0
    def force_unlock(self, redirect=True):
        """Steal the lock.

        If redirect is True, redirect back to the context URL, i.e. reload
        the page.
        """
        lockable = ILockable(self.context)
        lockable.unlock()
        if redirect:
            url = self.context.absolute_url()
            props_tool = getToolByName(self.context, 'portal_properties')
            if props_tool:
                types_use_view = props_tool.site_properties.typesUseViewActionInListings
                if self.context.portal_type in types_use_view:
                    url += '/view'

            self.request.RESPONSE.redirect(url)
Example #48
0
    def force_unlock(self, redirect=True):
        """Steal the lock.

        If redirect is True, redirect back to the context URL, i.e. reload
        the page.
        """
        lockable = ILockable(self.context)
        lockable.unlock()
        if redirect:
            url = self.context.absolute_url()
            registry = getUtility(IRegistry)
            types_use_view = registry.get(
                'plone.types_use_view_action_in_listings', [])
            if self.context.portal_type in types_use_view:
                url += '/view'

            self.request.RESPONSE.redirect(url)
Example #49
0
 def addTranslation(self, language, *args, **kwargs):
     """Adds a translation."""
     canonical = self.getCanonical()
     parent = aq_parent(aq_inner(self))
     if ITranslatable.providedBy(parent):
         parent = parent.getTranslation(language) or parent
     if self.hasTranslation(language):
         translation = self.getTranslation(language)
         raise AlreadyTranslated, translation.absolute_url()
     id = canonical.getId()
     while not parent.checkIdAvailable(id):
         id = '%s-%s' % (id, language)
     kwargs[config.KWARGS_TRANSLATION_KEY] = canonical
     if kwargs.get('language', None) != language:
         kwargs['language'] = language
     o = _createObjectByType(self.portal_type, parent, id, *args, **kwargs)
     # If there is a custom factory method that doesn't add the
     # translation relationship, make sure it is done now.
     if o.getCanonical() != canonical:
         o.addTranslationReference(canonical)
     self.invalidateTranslationCache()
     # Copy over the language independent fields
     schema = canonical.Schema()
     independent_fields = schema.filterFields(languageIndependent=True)
     for field in independent_fields:
         accessor = field.getEditAccessor(canonical)
         if not accessor:
             accessor = field.getAccessor(canonical)
         data = accessor()
         translation_mutator = getattr(o, field.translation_mutator)
         translation_mutator(data)
     # If this is a folder, move translated subobjects aswell.
     if self.isPrincipiaFolderish:
         moveids = []
         for obj in self.objectValues():
             if ITranslatable.providedBy(obj) and \
                        obj.getLanguage() == language:
                 lockable = ILockable(obj, None)
                 if lockable is not None and lockable.can_safely_unlock():
                     lockable.unlock()
                 moveids.append(obj.getId())
         if moveids:
             o.manage_pasteObjects(self.manage_cutObjects(moveids))
     o.reindexObject()
     if isDefaultPage(canonical, self.REQUEST):
         o._lp_default_page = True
Example #50
0
 def test_getLink_caching_showIcons(self):
     """Cache takes the 'showIcons' parameter into account."""
     adapted = IPrettyLink(self.folder)
     self.assertTrue(adapted.showIcons)
     ILockable(self.folder).lock()
     self.assertTrue(u"lock_icon.png" in adapted.getLink())
     adapted.showIcons = False
     self.assertFalse(u"lock_icon.png" in adapted.getLink())
    def xmChangeWorkflowState(self, uid, url):
        """Change the workflow state, currently only of a Task."""
        context = aq_inner(self.context)
        ksscore = self.getCommandSet('core')
        zopecommands = self.getCommandSet('zope')
        plonecommands = self.getCommandSet('plone')

        locking = ILockable(context, None)
        if locking is not None and not locking.can_safely_unlock():
            selector = ksscore.getHtmlIdSelector('plone-lock-status')
            zopecommands.refreshViewlet(selector, 'plone.abovecontent',
                                        'plone.lockinfo')
            plonecommands.refreshContentMenu()
            return self.render()

        (proto, host, path, query, anchor) = urlsplit(url)
        if not path.endswith('content_status_modify'):
            raise KSSExplicitError('only content_status_modify is handled')
        action = query.split("workflow_action=")[-1].split('&')[0]
        uid_catalog = getToolByName(context, 'uid_catalog')
        brain = uid_catalog(UID=uid)[0]
        obj = brain.getObject()
        # This may give a UnicodeDecodeError if the title has
        # non-ascii characters:
        # obj.content_status_modify(action)
        # So we do it manually, which is better anyway:
        wftool = getToolByName(context, 'portal_workflow')
        wftool.doActionFor(obj, action=action)
        if IXMStory.providedBy(self.context):
            # Only refresh content if the context is a Story,
            # otherwise you get too much tasks listed.
            selector = ksscore.getCssSelector('.contentViews')
            zopecommands.refreshViewlet(selector, 'plone.contentviews',
                                        'plone.contentviews')
            zopecommands.refreshProvider('.tasklist_table',
                                         'xm.tasklist.simple')
            plonecommands.refreshContentMenu()
        else:
            # In all other cases, we can at least refresh the part
            # that shows the workflow info for this item.
            wf_change = obj.restrictedTraverse('xm_workflow_change')
            html = wf_change()
            selector = ksscore.getHtmlIdSelector('id-%s' % uid)
            ksscore.replaceHTML(selector, html)
        self.issueAllPortalMessages()
        self.cancelRedirect()
Example #52
0
    def force_unlock(self, redirect=True):
        """Steal the lock.

        If redirect is True, redirect back to the context URL, i.e. reload
        the page.
        """
        lockable = ILockable(self.context)
        lockable.unlock()
        if redirect:
            url = self.context.absolute_url()
            props_tool = getToolByName(self.context, 'portal_properties')
            if props_tool:
                types_use_view = props_tool.site_properties.typesUseViewActionInListings
                if self.context.portal_type in types_use_view:
                    url += '/view'

            self.request.RESPONSE.redirect(url)
Example #53
0
    def _set_id(self, value):
        """ """
        context = aq_inner(self.context)
        parent = aq_parent(context)
        if not value:
            # plone.dexterity.fti.DexterityFTI
            factory_info = context.getTypeInfo()
            new_id = generate_content_id(factory_info.getId())
        # else add prefix/suffix with user provided value?
        else:
            new_id = value

        if parent is None:
            # Object hasn't been added to graph yet; just set directly
            context.id = value
            return

        if getattr(aq_base(context), 'id', None):
            transaction.savepoint()
            locked = False
            lockable = ILockable(context, None)
            if lockable is not None and lockable.locked():
                locked = True
                lockable.unlock()
            parent.manage_renameObject(context.getId(), new_id)
            if locked:
                lockable.lock()
        else:
            context.id = new_id
Example #54
0
 def delete(self):
     obj = self.get_by_uid(self.request.get('uid'))
     lockable = ILockable(obj, None)
     if lockable and lockable.locked():
         lockable.clear_locks()
     try:
         api.content.delete(obj)
         api.portal.show_message(
             'Successfully deleted "%s" located at: %s' %
             (unidecode(obj.Title()), self.get_path(obj)),
             self.request,
             type='warning')
     except LinkIntegrityNotificationException:
         api.portal.show_message(
             'Can not delete "%s" located at: %s because it is still linked.'
             % (unidecode(obj.Title()), self.get_path(obj)),
             self.request,
             type='warning')
Example #55
0
    def test_submit_additional_document(self):
        self.login(self.administrator)
        ori_document = self.subdocument
        with self.observe_children(self.submitted_proposal) as children:
            with self.login(self.dossier_responsible):
                self.proposal.submit_additional_document(ori_document)

        self.assertEquals(1, len(children['added']))
        submitted_document, = children['added']
        self.assertEqual(ori_document.Title(), submitted_document.Title())
        self.assertEqual(ori_document.file.filename, submitted_document.file.filename)

        self.assertSubmittedDocumentCreated(self.proposal, ori_document)

        # submitted document should be locked by custom lock
        lockable = ILockable(submitted_document)
        self.assertTrue(lockable.locked())
        self.assertFalse(lockable.can_safely_unlock(MEETING_SUBMITTED_LOCK))
    def update(self):
        if (getattr(self.context, "collective_immediatecreate", None) !=
                "initial"  # noqa: W503
            ):
            url = self.context.absolute_url() + "/edit"
            url = addTokenToUrl(url)
            raise Redirect(url)
        self.portal_type = self.context.portal_type

        if ILocking.providedBy(self.context):
            lockable = ILockable(self.context)
            if lockable.locked():
                lockable.unlock()

        super().update()

        # fire the edit begun only if no action was executed
        if len(self.actions.executedActions) == 0:
            notify(EditBegunEvent(self.context))
Example #57
0
    def lock_info(self):
        """Get information about the current lock, a dict containing:

        creator - the id of the user who created the lock
        fullname - the full name of the lock creator
        author_page - a link to the home page of the author
        time - the creation time of the lock
        time_difference - a string representing the time since the lock was
        acquired.
        """

        portal_membership = getToolByName(self.context, 'portal_membership')
        portal_url = getToolByName(self.context, 'portal_url')
        lockable = ILockable(aq_inner(self.context))
        url = portal_url()
        for info in lockable.lock_info():
            creator = info['creator']
            time = info['time']
            token = info['token']
            lock_type = info['type']
            # Get the fullname, but remember that the creator may not
            # be a member, but only Authenticated or even anonymous.
            # Same for the author_page
            fullname = ''
            author_page = ''
            member = portal_membership.getMemberById(creator)
            if member:
                fullname = member.getProperty('fullname', '')
                author_page = "%s/author/%s" % (url, creator)
            if fullname == '':
                fullname = creator or _('label_an_anonymous_user',
                                        u'an anonymous user')
            time_difference = self._getNiceTimeDifference(time)

            return {
                'creator': creator,
                'fullname': fullname,
                'author_page': author_page,
                'time': time,
                'time_difference': time_difference,
                'token': token,
                'type': lock_type,
            }
Example #58
0
    def test_lock_creation_removes_expired_locks_for_same_object(self):
        expired_lock = create(
            Builder('lock').of_obj(self.wrapper).having(
                time=utcnow_tz_aware() - timedelta(seconds=1000)))

        ILockable(self.wrapper).lock()

        locks = Lock.query.all()
        self.assertEquals(1, len(locks))
        self.assertNotIn(expired_lock, locks)
 def test_database_entry_is_deleted_when_removing_submitted_proposal(self):
     self.login(self.manager)
     submitted_document = self.submitted_proposal.get_documents()[0]
     self.assertIsNotNone(
         SubmittedDocument.query.get_by_target(submitted_document))
     # Submitted proposals are locked with an unstealable lock
     ILockable(submitted_document).clear_locks()
     api.content.delete(submitted_document)
     self.assertIsNone(
         SubmittedDocument.query.get_by_target(submitted_document))
Example #60
0
 def empty(self):
     for item in [
             i
             for i in self.catalog(trashed=True,
                                   object_provides=ITrashed.__identifier__)
     ]:
         obj = item.getObject()
         lockable = ILockable(obj, None)
         if lockable and lockable.locked():
             lockable.clear_locks()
         try:
             api.content.delete(obj, check_linkintegrity=False)
         except LinkIntegrityNotificationException:
             # could be a folder that has been deleted
             api.portal.show_message(
                 'Some content could not be removed because it is still linked '
                 'to other content on the site.',
                 self.request,
                 type='warning')
     api.portal.show_message('Trash emptied', self.request, type='warning')