def test_getLink_caching_locking(self): """Cache takes locking into account.""" ILockable(self.folder).lock() self.assertTrue(u"lock_icon.png" in IPrettyLink(self.folder).getLink()) ILockable(self.folder).unlock() self.assertFalse( u"lock_icon.png" in IPrettyLink(self.folder).getLink())
def test_cancelling_protocol_unlock_meeting(self, browser): browser.login().open(self.meeting.get_url(view='protocol')) lock_infos = ILockable( MeetingWrapper.wrap(self.committee, self.meeting)).lock_info() self.assertEquals(1, len(lock_infos)) browser.find('Close').click() self.assertEquals([], ILockable( MeetingWrapper.wrap(self.committee, self.meeting)).lock_info())
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)
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 migrate(self, unittest=0): """Migrates the object """ beforeChange, afterChange = self.getMigrationMethods() # Unlock according to plone.locking: lockable = ILockable(self.old, None) if lockable and lockable.locked(): lockable.unlock() # Unlock according to webdav: if self.old.wl_isLocked(): self.old.wl_clearLocks() 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()
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())
def test_lock_token_contains_object_type_and_is_separated_with_a_colon( self): lockable = ILockable(self.wrapper) lockable.lock() lock = Lock.query.first() self.assertEqual(u'Meeting:1', lock.token)
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 handle_delete(self, action): title = safe_unicode(self.context.Title()) parent = aq_parent(aq_inner(self.context)) # has the context object been acquired from a place it should not have # been? if self.context.aq_chain == self.context.aq_inner.aq_chain: if self.items_to_delete > 120: tasks.delete_items.delay([IUUID(self.context)]) IStatusMessage(self.request).add( """ You have selected to delete %i items which is a large amount. This action can take a long time to accomplish. We will email you when the content is done being deleted.""" % self.items_to_delete, 'error') else: if self.is_locked: # force unlock before delete... lockable = ILockable(self.context) lockable.clear_locks() parent.manage_delObjects(self.context.getId(), self.request) IStatusMessage(self.request).add( _(u'${title} has been deleted.', mapping={u'title': title})) else: IStatusMessage(self.request).add( _(u'"${title}" has already been deleted', mapping={u'title': title})) self.request.response.redirect(parent.absolute_url())
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'))
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()
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)
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 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()
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
def test_force_unlock_clears_lock(self, browser): self.login(self.regular_user, browser) with freeze(FREEZE_DATE): oc_url = self.fetch_document_checkout_oc_url( browser, self.document) expected_token = { u'action': u'checkout', u'documents': [u'createtreatydossiers000000000002'], u'exp': 4121033100, u'sub': u'kathi.barfuss', u'url': u'http://nohost/plone/oc_checkout', } raw_token = oc_url.split(':')[-1] token = jwt.decode(raw_token, JWT_SIGNING_SECRET_PLONE, algorithms=('HS256', )) self.assertEqual(expected_token, token) lockable = ILockable(self.document) self.lock_document(browser, raw_token, self.document) self.assertTrue(lockable.locked()) self.login(self.manager, browser) browser.open(self.document) browser.click_on("Unlock") self.assertFalse(lockable.locked())
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())
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())
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)
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()
def test_update_locked_object_without_token_fails(self): lockable = ILockable(self.doc) lockable.lock() transaction.commit() response = self.api_session.patch("/", json={"title": "New Title"}) transaction.commit() self.assertEqual(response.status_code, 403) self.assertEqual(self.doc.Title(), "My Document")
def test_lock_info_for_locked_object(self): lockable = ILockable(self.doc) lockable.lock() transaction.commit() response = self.api_session.get("/@lock") self.assertEqual(response.status_code, 200) self.assertTrue(response.json()["locked"])
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)
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())
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()
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 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()
def test_unlock_object(self): lockable = ILockable(self.doc) lockable.lock() transaction.commit() response = self.api_session.delete("/@lock") transaction.commit() self.assertEqual(response.status_code, 200) self.assertFalse(lockable.locked())
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())
def webdav_lock(obj): """Returns the WebDAV LockItem""" lockable = ILockable(obj, None) if lockable is None: return lock_info = lockable.lock_info() if len(lock_info) > 0: token = lock_info[0]["token"] return obj.wl_getLock(token)