def test_delete_object_when_locked(self): from plone.app.content.browser.contents.delete import DeleteActionView lockable = IRefreshableLockable(self.portal.page) lockable.lock() view = DeleteActionView(self.portal, self.request) view() self.assertEqual(len(view.errors), 1)
def test_multi_checkin_does_not_checkin_locked_documents(self, browser): self.login(self.regular_user, browser) browser.open(self.document, view='tabbedview_view-overview') browser.find('Checkout and edit').click() browser.open(self.subdocument, view='tabbedview_view-overview') browser.find('Checkout and edit').click() lockable = IRefreshableLockable(self.document) lockable.lock() browser.open( self.dossier, method='POST', data={ 'paths': [ obj2brain(self.document).getPath(), obj2brain(self.subdocument).getPath(), ], 'checkin_without_comment:method': 1, '_authenticator': createToken(), }, ) manager = getMultiAdapter((self.document, self.portal.REQUEST), ICheckinCheckoutManager) self.assertEquals('kathi.barfuss', manager.get_checked_out_by()) manager = getMultiAdapter((self.subdocument, self.portal.REQUEST), ICheckinCheckoutManager) self.assertEquals(None, manager.get_checked_out_by()) self.assertEquals([u'Could not check in document Vertr\xe4gsentwurf'], error_messages())
def test_delete_object_when_locked(self): from plone.app.content.browser.contents.delete import DeleteActionView lockable = IRefreshableLockable(self.portal.page) lockable.lock() view = DeleteActionView(self.portal, self.request) view() self.assertEquals(len(view.errors), 1)
def test_editor_can_unlock(self): # Default Plone behavior: Editor can unlock other's people lock portal = self.layer['portal'] login(portal, 'user1') lockable = IRefreshableLockable(portal.document) self.assertTrue(lockable._user_can_unlock()) self.assertTrue(lockable.stealable())
def get_lock_infos(self): results = [] catalog = self.context.portal_catalog docs = catalog(portal_type='opengever.document.document') for doc in docs: obj = doc.getObject() lockable = IRefreshableLockable(obj) lock_info = lockable.lock_info() if not lock_info == []: infos = {} infos['title'] = obj.Title() infos['url'] = obj.absolute_url() # Ignoring multiple locks for now infos['token'] = lock_info[0]['token'] infos['creator'] = lock_info[0]['creator'] lock_time = datetime.fromtimestamp(lock_info[0]['time']) duration = datetime.now() - lock_time infos['time'] = lock_time.strftime("%Y-%m-%d %H:%M:%S") infos['duration'] = strfdelta(duration, "{days}d {hours}h {minutes}m {seconds}s") infos['type'] = lock_info[0]['type'] manager = getMultiAdapter((obj, obj.REQUEST), ICheckinCheckoutManager) infos['checked_out'] = manager.get_checked_out_by() results.append(infos) return results
def clear_locks(self): """Clears any WebDAV locks on the adapted document left over by ExternalEditor. """ lockable = IRefreshableLockable(self.context) if lockable and lockable.locked(): lockable.clear_locks()
def refresh_lock(self, redirect=True): """Reset the lock start time """ lockable = IRefreshableLockable(self.context, None) if lockable is not None: lockable.refresh_lock() if redirect: self.redirect()
def create_lock(self, redirect=True): """Lock the object if it is unlocked """ lockable = IRefreshableLockable(self.context, None) if lockable is not None: lockable.lock() if redirect: self.redirect()
def is_locked(self): """Returns True if a user has a WebDAV lock on the adapted document, False otherwise. """ lockable = IRefreshableLockable(self.context) # List of all users that hold a lock on the document if lockable and lockable.locked(): return True return False
def reply(self): lockable = IRefreshableLockable(self.context, None) if lockable is not None: lockable.refresh_lock() # Disable CSRF protection if "IDisableCSRFProtection" in dir(plone.protect.interfaces): alsoProvides(self.request, plone.protect.interfaces.IDisableCSRFProtection) return lock_info(self.context)
def test_force_checkin_clears_lock(self): self.login(self.regular_user) manager = getMultiAdapter((self.document, self.portal.REQUEST), ICheckinCheckoutManager) manager.checkout() self.assertFalse(IRefreshableLockable(self.document).locked()) IRefreshableLockable(self.document).lock() self.assertTrue(IRefreshableLockable(self.document).locked()) self.login(self.administrator) manager.checkin(comment="Force checkin") self.assertFalse(IRefreshableLockable(self.document).locked())
def test_migrates_webdav_locks(self): self.login('HANS.MUSTER') document = create(Builder('document') .with_asset_file('text.txt') .checked_out_by('HANS.MUSTER')) lockable = IRefreshableLockable(document) lockable.lock() CheckedOutDocsMigrator( self.portal, {'HANS.MUSTER': 'hans.muster'}, 'move').migrate() self.assertEqual('hans.muster', lockable.lock_info()[0]['creator'])
def test_checkout_not_possible_if_locked_by_another_user(self, browser): self.login(self.dossier_responsible, browser) lockable = IRefreshableLockable(self.document) lockable.lock() self.login(self.regular_user, browser) browser.open(self.document, view='tabbedview_view-overview') self.assertFalse( browser.css('a.function-edit'), 'There should be no edit link', )
def test_checkout_not_possible_if_locked_by_another_user(self, browser): second_user = create(Builder('user').with_roles('Member')) login(self.portal, second_user.getId()) lockable = IRefreshableLockable(self.document) lockable.lock() logout() login(self.portal, TEST_USER_NAME) transaction.commit() browser.login().visit(self.document, view='tabbedview_view-overview') self.assertFalse(browser.css('a.function-edit'), 'There should be no edit link')
def test_upload_box_is_hidden_when_document_is_locked(self, browser): document = create(Builder('document').within(self.dossier)) IRefreshableLockable(document).lock() browser.login().open(document) self.assertEquals([], browser.css('#uploadbox'), 'uploadbox is wrongly displayed')
def test_raises_unauthorized_when_document_is_locked(self): self.login(self.regular_user) IRefreshableLockable(self.document).lock() with self.assertRaises(Unauthorized): create( Builder('quickuploaded_document').within( self.document).with_data('text'))
def test_edit_form_document_is_checked_out(self, browser): # checkout the document manager = queryMultiAdapter((self.document, self.document.REQUEST), ICheckinCheckoutManager) manager.checkout() transaction.commit() browser.login().open(self.document, view='edit') self.assertEqual( '{}/file_download_confirmation'.format( self.document.absolute_url()), browser.css('#form-widgets-file a.link-overlay').first.get('href')) # edit should be posssible self.assertEqual([ 'Keep existing file', 'Remove existing file', 'Replace with new file' ], browser.css('#form-widgets-file label').text) IRefreshableLockable(self.document).unlock() transaction.commit() manager.cancel()
def test_returns_lock_info_viewlet_if_locked(self, browser): self.login(self.regular_user) IRefreshableLockable(self.document).lock() adapter = getMultiAdapter((self.document, self.request), IBumblebeeOverlay) browser.open_html(adapter.render_lock_info_viewlet()) self.assertEqual(1, len(browser.css('.portalMessage')))
def is_edit_metadata_available(self): # XXX object orient me, the object should know some of this stuff if self.is_checked_out_by_another_user(): return False if IRefreshableLockable(self.context).locked(): return False return api.user.has_permission( 'Modify portal content', obj=self.context)
def reply(self): data = json_body(self.request) lockable = IRefreshableLockable(self.context, None) if lockable is not None: lockable.lock() if "stealable" in data and not data["stealable"]: alsoProvides(self.context, INonStealableLock) if "timeout" in data: lock_item = webdav_lock(self.context) lock_item.setTimeout("Second-%s" % data["timeout"]) # Disable CSRF protection if "IDisableCSRFProtection" in dir(plone.protect.interfaces): alsoProvides(self.request, plone.protect.interfaces.IDisableCSRFProtection) return lock_info(self.context)
def _migrate_checked_out_doc(self, doc, old_userid, new_userid): # Migrate "checked out by" information and reindex manager = getMultiAdapter((doc, self.portal.REQUEST), ICheckinCheckoutManager) key = CHECKIN_CHECKOUT_ANNOTATIONS_KEY if manager.annotations[key] == old_userid: manager.annotations[key] = new_userid logger.info('Reindexing %s' % '/'.join(doc.getPhysicalPath())) doc.reindexObject(idxs=['checked_out']) # Migrate WebDAV locks lockable = IRefreshableLockable(doc) if lockable.locked(): locks = doc.wl_lockmapping().values() for lock in locks: if not lock.getCreator(): continue if lock._creator[1] == old_userid: lock._creator = (lock._creator[0], new_userid)
def test_upload_box_is_hidden_when_document_is_locked(self, browser): self.login(self.regular_user, browser) manager = queryMultiAdapter((self.document, self.request), ICheckinCheckoutManager) manager.checkout() IRefreshableLockable(self.document).lock() browser.open(self.document) self.assertEquals([], browser.css('#uploadbox'), 'uploadbox is wrongly displayed')
def test_single_locked_checkin_with_comment(self, browser): self.login(self.regular_user, browser) browser.open(self.document, view='tabbedview_view-overview') browser.find('Checkout and edit').click() # Lock document IRefreshableLockable(self.document).lock() browser.open(self.document) # open checkin form browser.css('#checkin_with_comment').first.click() assert_message( ' '.join(( 'This document is currently being worked on.', 'When you check it in manually you will lose the changes.', 'Please allow for the process to be finished first.', )) ) self.assertIn( 'Checkin anyway', browser.css('#form-buttons-button_checkin_anyway')[0].outerHTML ) self.assertNotIn( 'Cancel Checkout', browser.css('.contentViews a').text ) # fill and submit checkin form journal_comment = u'Checkinerino' browser.fill({ u'Journal Comment': journal_comment, }) browser.css('#form-buttons-button_checkin_anyway').first.click() manager = getMultiAdapter( (self.document, self.portal.REQUEST), ICheckinCheckoutManager, ) self.assertEquals(None, manager.get_checked_out_by()) self.assert_journal_entry( self.document, DOCUMENT_CHECKED_IN, u'Document checked in', comment=journal_comment, )
def test_checkin_without_comment_action_button_not_rendered_for_locked_documents(self, browser): self.login(self.regular_user, browser) browser.open(self.document, view='tabbedview_view-overview') browser.find('Checkout and edit').click() lockable = IRefreshableLockable(self.document) lockable.lock() # Tabbedview gets in the way of the redirect so we'll have to revisit browser.open(self.document, view='tabbedview_view-overview') file_actions = [ 'Edit', 'Checkin with comment', 'Download copy', ] self.assertEquals( file_actions, browser.css('.file-action-buttons a').text, )
def test_checkin_without_comment_portal_action_not_rendered_for_locked_documents( self, browser): self.login(self.regular_user, browser) browser.open(self.document, view='tabbedview_view-overview') browser.find('Checkout and edit').click() lockable = IRefreshableLockable(self.document) lockable.lock() browser.open(self.document) document_portal_actions = [ 'Edit metadata', u'Actions \u25bc', 'Properties', u'Checkin \u25bc', 'with comment', ] self.assertEquals(document_portal_actions, browser.css('#edit-bar a').text)
def test_can_remove_my_lock(self): portal = self.layer['portal'] login(portal, 'user1') lockable = IRefreshableLockable(portal.document) lockable.lock() setRoles(portal, 'user1', ['Member', ]) lockable = IRefreshableLockable(portal.document) # Not editor anymore... self.assertFalse(lockable._user_can_unlock()) # ...but can unlock self.assertTrue(lockable._lock_is_mine()) self.assertTrue(lockable.stealable())
def test_checkin_without_comment_action_button_not_rendered_for_locked_documents(self, browser): # noqa self.login(self.regular_user, browser) browser.open(self.document, view='tabbedview_view-overview') browser.find('Checkout and edit').click() lockable = IRefreshableLockable(self.document) lockable.lock() # Tabbedview gets in the way of the redirect so we'll have to revisit browser.open(self.document, view='tabbedview_view-overview') file_actions = [ 'Checkout and edit', 'Checkin with comment', 'Download copy', 'PDF Preview', ] self.assertEquals( file_actions, browser.css('.file-action-buttons a').text, )
def test_checkout_when_locked(self): """Test that it's not possible to check out the document if its locked by another user. """ old_sm = getSecurityManager() # Change security context to 'other_user' to lock the document user = self.portal.acl_users.getUser('other_user') user = user.__of__(self.portal.acl_users) newSecurityManager(self.portal, user) # Let user 'other_user' lock the document lockable = IRefreshableLockable(self.document4) lockable.lock() # Restore previous security context (test_user_1) setSecurityManager(old_sm) transaction.commit() self.browser.open( '%s/tabbedview_view-overview' % self.document4.absolute_url()) # Editing the document shouldn't be possible self.assertNotIn('editing_document', self.browser.contents)
def test_checkin_without_comment_portal_action_not_rendered_for_locked_documents(self, browser): # noqa self.login(self.regular_user, browser) browser.open(self.document, view='tabbedview_view-overview') browser.find('Checkout and edit').click() lockable = IRefreshableLockable(self.document) lockable.lock() browser.open(self.document) document_portal_actions = [ 'Edit metadata', u'Actions \u25bc', 'Copy Item', 'Properties', u'Checkin \u25bc', 'with comment', ] self.assertEquals( document_portal_actions, browser.css('#edit-bar a').text )
def test_checkout_when_locked(self): """Test that it's not possible to check out the document if its locked by another user. """ old_sm = getSecurityManager() # Change security context to 'other_user' to lock the document user = self.portal.acl_users.getUser('other_user') user = user.__of__(self.portal.acl_users) newSecurityManager(self.portal, user) # Let user 'other_user' lock the document lockable = IRefreshableLockable(self.document4) lockable.lock() # Restore previous security context (test_user_1) setSecurityManager(old_sm) transaction.commit() self.browser.open('%s/tabbedview_view-overview' % self.document4.absolute_url()) # Editing the document shouldn't be possible self.assertNotIn('editing_document', self.browser.contents)
def test_returns_lock_info_viewlet_if_locked(self, browser): create( Builder('user').with_userid('bond').with_roles('Member', 'Reader')) dossier = create(Builder('dossier')) document = create( Builder('document').within(dossier).with_dummy_content()) IRefreshableLockable(document).lock() login(self.portal, 'bond') adapter = getMultiAdapter((document, self.request), IBumblebeeOverlay) browser.open_html(adapter.render_lock_info_viewlet()) self.assertEqual(1, len(browser.css('.portalMessage')))
def test_checkin_anyway_shown_for_locked_documents(self, browser): self.login(self.regular_user, browser) browser.open(self.document, view='tabbedview_view-overview') browser.find('Checkout and edit').click() browser.open(self.document) browser.css('#checkin_with_comment').first.click() self.assertEqual(0, len(browser.css('#form-buttons-button_checkin_anyway'))) self.assertEqual(browser.css('#form-buttons-button_checkin').first.name, 'form.buttons.button_checkin') # Lock document IRefreshableLockable(self.document).lock() browser.open(self.document) browser.css('#checkin_with_comment').first.click() self.assertEqual(0, len(browser.css('#form-buttons-button_checkin'))) self.assertEqual(browser.css('#form-buttons-button_checkin_anyway').first.name, 'form.buttons.button_checkin_anyway')
def is_cancel_allowed(self): """Checks whether the user is able to cancel a checkout.""" current_user_id = getSecurityManager().getUser().getId() current_checkout_id = self.get_checked_out_by() # is the document checked out? # is the document not locked? # is it versionable? # is the user allowed to cancel? # is the user either the one who owns the checkout or a manager? if (current_checkout_id and not IRefreshableLockable(self.context).locked() and self.versioner.is_versionable() and self.check_permission('opengever.document: Cancel') and bool(current_checkout_id == current_user_id or self.check_permission('Manage portal'))): return True return False
def test_api(self): # create a defaultfolder pr = getToolByName(self.portal, 'portal_repository') # create a document, and get CheckinCheckoutManager for the document manager = getMultiAdapter( (self.doc1, self.portal.REQUEST), ICheckinCheckoutManager) manager2 = getMultiAdapter( (self.doc2, self.portal.REQUEST), ICheckinCheckoutManager) # Checkout: # checkout should now allowed, but just for a user with authorization self.assertTrue(manager.is_checkout_allowed()) # the annotations should be still empty self.assertIsNone(manager.get_checked_out_by()) # checkout the document manager.checkout() self.assertEquals('test_user_1_', manager.get_checked_out_by()) # cancelling and checkin should be allowed for the 'test_user_1_' self.assertTrue(manager.is_checkin_allowed()) self.assertTrue(manager.is_cancel_allowed()) self.assertFalse(manager.is_checkout_allowed()) # Checkout when locked by another user: # Create a second user to test locking and checkout self.portal.acl_users.userFolderAddUser( 'other_user', 'secret', ['Member'], []) # Checkout should first be allowed self.assertTrue(manager2.is_checkout_allowed()) # Switch to different user and lock the document logout() login(self.portal, 'other_user') setRoles( self.portal, 'other_user', ['Manager', 'Editor', 'Contributor']) lockable = IRefreshableLockable(self.doc2) lockable.lock() # Log back in as the regular test user logout() login(self.portal, TEST_USER_NAME) setRoles( self.portal, TEST_USER_ID, ['Manager', 'Editor', 'Contributor']) # Checkout should not be allowed since the document is already # locked by an another user self.assertFalse(manager2.is_checkout_allowed()) # checkin and cancelling: mok_file2 = NamedBlobFile('blubb blubb', filename=u"blubb.txt") self.doc1.file = mok_file2 manager.checkin(comment="Test commit Nr. 1") transaction.commit() # document isn't checked out and the old object is in the history self.assertIsNone(manager.get_checked_out_by()) self.assertEquals(u'Document1.doc', pr.retrieve(self.doc1, 0).object.file.filename) self.assertEquals(u'blubb.txt', self.doc1.file.filename) manager.checkout() self.assertEquals('test_user_1_', manager.get_checked_out_by()) manager.cancel() pr.getHistoryMetadata(self.doc1).retrieve(2) self.assertIsNone(manager.get_checked_out_by())
def test_api(self): # create a defaultfolder pr = getToolByName(self.portal, "portal_repository") # create a document, and get the CheckinCheckoutManager for the document mok_file1 = NamedBlobFile("bla bla", filename=u"test.txt") mok_file2 = NamedBlobFile("bla bla", filename=u"test.txt") doc1 = createContentInContainer( self.portal, "opengever.document.document", title=u"Doc \xf6ne", document_author=u"Hugo Boss", document_date=datetime.date(2011, 1, 1), file=mok_file1, ) doc2 = createContentInContainer(self.portal, "opengever.document.document", title=u"Doc three", file=mok_file2) manager = getMultiAdapter((doc1, self.portal.REQUEST), ICheckinCheckoutManager) manager2 = getMultiAdapter((doc2, self.portal.REQUEST), ICheckinCheckoutManager) # Checkout: # checkout should now allowed, but just for a user with authorization self.assertTrue(manager.is_checkout_allowed()) # the annotations should be still empty self.assertEquals(None, manager.checked_out()) # checkout the document manager.checkout() self.assertEquals("test_user_1_", manager.checked_out()) # cancelling and checkin should be allowed for the 'test_user_1_' self.assertTrue(manager.is_checkin_allowed()) self.assertTrue(manager.is_cancel_allowed()) self.assertFalse(manager.is_checkout_allowed()) # Checkout when locked by another user: # Create a second user to test locking and checkout self.portal.acl_users.userFolderAddUser("other_user", "secret", ["Member"], []) # Checkout should first be allowed self.assertTrue(manager2.is_checkout_allowed()) # Switch to different user and lock the document logout() login(self.portal, "other_user") setRoles(self.portal, "other_user", ["Manager", "Editor", "Contributor"]) lockable = IRefreshableLockable(doc2) lockable.lock() # Log back in as the regular test user logout() login(self.portal, TEST_USER_NAME) setRoles(self.portal, TEST_USER_ID, ["Manager", "Editor", "Contributor"]) # Checkout should not be allowed since the document is locked by another user self.assertFalse(manager2.is_checkout_allowed()) # checkin and cancelling: mok_file2 = NamedBlobFile("blubb blubb", filename=u"blubb.txt") doc1.file = mok_file2 manager.checkin(comment="Test commit Nr. 1") transaction.commit() # document isn't checked out and the old object is in the history self.assertEquals(None, manager.checked_out()) self.assertEquals(u"doc-one.txt", pr.retrieve(doc1, 0).object.file.filename) self.assertEquals(u"blubb.txt", doc1.file.filename) manager.checkout() self.assertEquals("test_user_1_", manager.checked_out()) manager.cancel() pr.getHistoryMetadata(doc1).retrieve(2) self.assertEquals(None, manager.checked_out())
def is_document_locked(self): return IRefreshableLockable(self.context).locked()
def refresh_lock(self): """Reset the lock start time """ lockable = IRefreshableLockable(self.context, None) if lockable is not None: lockable.refresh_lock()
def create_lock(self): """Lock the object if it is unlocked """ lockable = IRefreshableLockable(self.context, None) if lockable is not None: lockable.lock()
def isLocked(context): lockable = IRefreshableLockable(context) lockable.locked()
def unlockContext(context): lockable = IRefreshableLockable(context) lockable.unlock(STRUCTURALCONTENT_LOCK)
def lockContext(context): lockable = IRefreshableLockable(context) lockable.lock(STRUCTURALCONTENT_LOCK) token = lockable.lock_info()[0]["token"] lock = lockable.context.wl_getLock(token) lock.setTimeout(MAXTIMEOUT)