def canExecute(self, rule=None, req=None): if rule is not None or req is not None: msg = ('In the next releases the rule and req parameters ' 'will not be supported anymore. ' 'In case you want to customize this product ' 'use the request and rule properties') warnings.warn(msg, DeprecationWarning) if req is None: req = self.request if req.environ.get('disable.auditlog', False): return False event = self.event obj = event.object event_iface = next(event.__implemented__.interfaces()) # for archetypes we need to make sure we're getting the right moved # event here so we do not duplicate if not IObjectEditedEvent.providedBy(event): if rule is None: rule = self.rule if event_iface != rule.rule.event: return False # if archetypes, initialization also does move events if (IObjectMovedEvent.providedBy(event) and IBaseObject.providedBy(obj) and obj.checkCreationFlag()): return False return True
def extract_what(self): #Archetypes if IObjectInitializedEvent.providedBy(self.event): return 'created', self.get_object_modified_info() elif IObjectEditedEvent.providedBy(self.event): return 'modified', self.get_object_modified_info() # #TODO: plone.app.iterate # elif ICheckinEvent.providedBy(self.event): # return 'checkedin' # elif ICheckoutEvent.providedBy(self.event): # return 'checkedout' # elif IWorkingCopyDeletedEvent.providedBy(self.event): # return 'workingcopydeleted' # DCWorkflow elif IAfterTransitionEvent.providedBy(self.event): return 'statechanged', self.get_transition_info() # CMFCore (useless) # elif IActionSucceededEvent.providedBy(self.event): # return None # return 'statechanged', self.get_action_succeed_info() # zope # elif IObjectAddedEvent.providedBy(self.event): # return 'added', self.get_object_moved_info() elif IObjectCopiedEvent.providedBy(self.event): return 'copied', self.get_object_copied_info() elif IObjectMovedEvent.providedBy(self.event): return 'moved', self.get_object_moved_info() elif IObjectRemovedEvent.providedBy(self.event): return 'removed', self.get_object_moved_info() elif IObjectModifiedEvent.providedBy(self.event): return 'modified', self.get_object_modified_info() return None, {}
def testRenameEvents(self): self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('monty', ), ('python', )) self.assertEqual(len(getEvents()), 0) self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('foo', 'monty'), ('bar', 'python')) self.assertEqual(len(getEvents()), 1) events = getEvents(IObjectWillBeMovedEvent) self.assertEqual(len(events), 1) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].newName, 'bar') self.assertEqual( self.reflecto.manage_renameObjects(('foo', ), ('bar', )), ['foo']) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[1])) self.assertTrue(IObjectMovedEvent.providedBy(events[2])) self.assertEqual(events[2].oldName, 'foo') self.assertEqual(events[2].newName, 'bar') self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertTrue(events[3].object is self.reflecto)
def test_move_event(events): """If the item had a parent or name (as in a move or rename), we generate a move event, rather than an add event. """ container = {} # We create a first item item = Item() setitem(container, container.__setitem__, u'c1', item) # Add operation are "moved" events. assert len(events) == 2 event = events.popleft() assert IObjectAddedEvent.providedBy(event) event = events.popleft() assert IObjectModifiedEvent.providedBy(event) assert isinstance(event, ContainerModifiedEvent) # We created an item already contained. item = Item() item.__parent__, item.__name__ = container, 'c2' setitem(container, container.__setitem__, u'c2', item) assert not len(events) # We now rewrite 'c2' under another name # Thus, we created a move event : +1 modification +1 move. setitem(container, container.__setitem__, u'c3', item) assert len(container) == 3 event = events.popleft() assert IObjectMovedEvent.providedBy(event)
def testRenameEvents(self): self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('monty',), ('python',)) self.assertEqual(len(getEvents()), 0) self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('foo', 'monty'), ('bar', 'python')) self.assertEqual(len(getEvents()), 1) events = getEvents(IObjectWillBeMovedEvent) self.assertEqual(len(events), 1) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].newName, 'bar') self.assertEqual(self.reflecto.manage_renameObjects(('foo',), ('bar',)), ['foo']) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[1])) self.assertTrue(IObjectMovedEvent.providedBy(events[2])) self.assertEqual(events[2].oldName, 'foo') self.assertEqual(events[2].newName, 'bar') self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertTrue(events[3].object is self.reflecto)
def handleComentedObject(ob, event): if IObjectAddedEvent.providedBy(event): catalog_comments(ob) elif IObjectMovedEvent.providedBy(event): if event.newParent is not None: catalog_comments(ob) elif IObjectWillBeMovedEvent.providedBy(event): if event.oldParent is not None: uncatalog_comments(ob)
def __call__(self, event): if not IObjectMovedEvent.providedBy(event): # pylint: disable=no-value-for-parameter return False for intf in self.interfaces: try: if intf.providedBy(event.newParent): return True except (AttributeError, TypeError): if isinstance(event.newParent, intf): return True return False
def timeline_update(object_, event): iterations = [] if not IIteration.providedBy(object_): if IObjectMovedEvent.providedBy(event): for parent in [event.oldParent, event.newParent]: if parent: iterations.append(api.content.get_iteration(parent)) else: iterations.append(api.content.get_iteration(object_)) else: iterations.append(object_) for iteration in iterations: if iteration is not None: snapshot(iteration)
def canExecute(self, rule, req): event = self.event obj = event.object event_iface = [i for i in event.__implemented__.interfaces()][0] # for archetypes we need to make sure we're getting the right moved # event here so we do not duplicate if (not IObjectEditedEvent.providedBy(event) and rule is not None and event_iface != rule.rule.event): return False # if archetypes, initialization also does move events if (IObjectMovedEvent.providedBy(event) and IBaseObject.providedBy(obj) and obj.checkCreationFlag()): return False if req.environ.get('disable.auditlog', False): return False return True
def testCutEvents(self): cp = self.reflecto.manage_cutObjects(('foo',)) self.reflecto['subdir'].manage_pasteObjects(cp) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[0])) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].oldParent, self.reflecto) self.assertEqual(events[0].newName, 'foo') self.assertEqual(events[0].newParent, self.reflecto['subdir']) self.assertTrue(IObjectMovedEvent.providedBy(events[1])) self.assertEqual(events[1].object.getId(), 'foo') self.assertTrue(IContainerModifiedEvent.providedBy(events[2])) self.assertEqual(events[2].object, self.reflecto) self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertEqual(events[3].object, self.reflecto['subdir'])
def testCutEvents(self): cp = self.reflecto.manage_cutObjects(('foo', )) self.reflecto['subdir'].manage_pasteObjects(cp) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[0])) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].oldParent, self.reflecto) self.assertEqual(events[0].newName, 'foo') self.assertEqual(events[0].newParent, self.reflecto['subdir']) self.assertTrue(IObjectMovedEvent.providedBy(events[1])) self.assertEqual(events[1].object.getId(), 'foo') self.assertTrue(IContainerModifiedEvent.providedBy(events[2])) self.assertEqual(events[2].object, self.reflecto) self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertEqual(events[3].object, self.reflecto['subdir'])
def get_what_info(self, event): #Archetypes if IObjectEditedEvent.providedBy(event): return self.get_object_modified_info(event) elif IObjectInitializedEvent.providedBy(event): return self.get_object_modified_info(event) #plone elif IConfigurationChangedEvent.providedBy(event): return self.get_configuration_changed_info(event) # #plone.app.form (formlib) # elif IEditSavedEvent.providedBy(event): # return 'editsaved' # #plone.app.iterate # elif ICheckinEvent.providedBy(event): # return 'checkedin' # elif ICheckoutEvent.providedBy(event): # return 'checkedout' # elif IWorkingCopyDeletedEvent.providedBy(event): # return 'workingcopydeleted' # #plone.app.registry elif IRecordModifiedEvent.providedBy(event): return self.get_record_modified_info(event) # DCWorkflow elif ITransitionEvent.providedBy(event): return self.get_transition_info(event) # CMFCore elif IActionSucceededEvent.providedBy(event): return self.get_action_succeed_info(event) # zope elif IObjectCopiedEvent.providedBy(event): return self.get_object_copied_info(event) elif IObjectMovedEvent.providedBy(event): return self.get_object_moved_info(event) elif IObjectAddedEvent.providedBy(event): return self.get_object_moved_info(event) elif IObjectRemovedEvent.providedBy(event): return self.get_object_moved_info(event)
def canExecute(self, rule=None, req=None): if rule is not None or req is not None: msg = ( 'In the next releases the rule and req parameters ' 'will not be supported anymore. ' 'In case you want to customize this product ' 'use the request and rule properties' ) warnings.warn(msg, DeprecationWarning) if req is None: req = self.request if req.environ.get('disable.auditlog', False): return False event = self.event obj = event.object event_iface = next(event.__implemented__.interfaces()) # for archetypes we need to make sure we're getting the right moved # event here so we do not duplicate if not IObjectEditedEvent.providedBy(event): if rule is None: rule = self.rule if event_iface != rule.rule.event: return False # if archetypes, initialization also does move events if ( IObjectMovedEvent.providedBy(event) and IBaseObject.providedBy(obj) and obj.checkCreationFlag() ): return False return True
def subscriber(object_, event): if not IObjectMovedEvent.providedBy(event): snapshot(object_)
def getLogEntry(self): ''' Get's a log entry for your action ''' event = self.event obj = event.object data = {'info': ''} # order of those checks is important since some interfaces # base off the others if IPloneFormGenField.providedBy(obj): # if ploneformgen field, use parent object for modified data data['field'] = obj.getId() obj = aq_parent(obj) # the order of those interface checks matters since some interfaces # inherit from others if IObjectRemovedEvent.providedBy(event): # need to keep track of removed events so it doesn't get called # more than once for each object action = 'removed' elif (IObjectInitializedEvent.providedBy(event) or IObjectCreatedEvent.providedBy(event) or IObjectAddedEvent.providedBy(event)): action = 'added' elif IObjectMovedEvent.providedBy(event): # moves can also be renames. Check the parent object if event.oldParent == event.newParent: if 'Rename' not in self.rule.rule.title: # cut out here, double action for this event return {} data['info'] = 'previous id: %s' % event.oldName action = 'rename' else: if 'Moved' not in self.rule.rule.title: # step out immediately since this could be a double action return {} data['info'] = 'previous location: %s/%s' % ( '/'.join(event.oldParent.getPhysicalPath()), event.oldName, ) action = 'moved' elif IObjectModifiedEvent.providedBy(event): action = 'modified' elif IActionSucceededEvent.providedBy(event): data['info'] = 'workflow transition: %s; comments: %s' % ( event.action, self.get_history_comment(), ) action = 'workflow' elif IObjectClonedEvent.providedBy(event): action = 'copied' elif ICheckinEvent.providedBy(event): data['info'] = event.message action = 'checked in' self.request.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline elif IBeforeCheckoutEvent.providedBy(event): action = 'checked out' self.request.environ['disable.auditlog'] = True elif ICancelCheckoutEvent.providedBy(event): action = 'cancel check out' self.request.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline else: logger.warn('no action matched') return {} if IWorkingCopy.providedBy(obj): # if working copy, iterate, check if Track Working Copies is # enabled if not self.trackWorkingCopies: # if not enabled, we only care about checked messages if 'check' not in action: return {} # if enabled in control panel, use original object and move # working copy path to working_copy data['working_copy'] = '/'.join(obj.getPhysicalPath()) relationships = obj.getReferences(WorkingCopyRelation.relationship) # check relationships, if none, something is wrong, not logging # action if len(relationships) <= 0: return {} obj = relationships[0] data.update(self._getObjectInfo(obj)) data['action'] = action return data
def getLogEntry(self): ''' Get's a log entry for your action ''' event = self.event obj = event.object data = {'info': ''} # order of those checks is important since some interfaces # base off the others if IPloneFormGenField.providedBy(obj): # if ploneformgen field, use parent object for modified data data['field'] = obj.getId() obj = aq_parent(obj) # the order of those interface checks matters since some interfaces # inherit from others if IObjectRemovedEvent.providedBy(event): # need to keep track of removed events so it doesn't get called # more than once for each object action = 'removed' elif ( IObjectInitializedEvent.providedBy(event) or IObjectCreatedEvent.providedBy(event) or IObjectAddedEvent.providedBy(event) ): action = 'added' elif IObjectMovedEvent.providedBy(event): # moves can also be renames. Check the parent object if event.oldParent == event.newParent: if 'Rename' not in self.rule.rule.title: # cut out here, double action for this event return {} data['info'] = 'previous id: %s' % event.oldName action = 'rename' else: if 'Moved' not in self.rule.rule.title: # step out immediately since this could be a double action return {} data['info'] = 'previous location: %s/%s' % ( '/'.join(event.oldParent.getPhysicalPath()), event.oldName, ) action = 'moved' elif IObjectModifiedEvent.providedBy(event): action = 'modified' elif IActionSucceededEvent.providedBy(event): data['info'] = 'workflow transition: %s; comments: %s' % ( event.action, self.get_history_comment(), ) action = 'workflow' elif IObjectClonedEvent.providedBy(event): action = 'copied' elif ICheckinEvent.providedBy(event): data['info'] = event.message action = 'checked in' self.request.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline elif IBeforeCheckoutEvent.providedBy(event): action = 'checked out' self.request.environ['disable.auditlog'] = True elif ICancelCheckoutEvent.providedBy(event): action = 'cancel check out' self.request.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline else: logger.warn('no action matched') return {} if IWorkingCopy.providedBy(obj): # if working copy, iterate, check if Track Working Copies is # enabled if not self.trackWorkingCopies: # if not enabled, we only care about checked messages if 'check' not in action: return {} # if enabled in control panel, use original object and move # working copy path to working_copy data['working_copy'] = '/'.join(obj.getPhysicalPath()) relationships = obj.getReferences( WorkingCopyRelation.relationship) # check relationships, if none, something is wrong, not logging # action if len(relationships) <= 0: return {} obj = relationships[0] data.update(self._getObjectInfo(obj)) data['action'] = action return data
def __call__(self): req = getRequest() if req.environ.get('disable.auditlog', False): return True event = self.event obj = event.object # order of those checks is important since some interfaces # base off the others rule = inspect.stack()[1][0].f_locals.get('self', None) registry = getUtility(IRegistry) trackWorkingCopies = registry['collective.auditlog.interfaces.IAuditLogSettings.trackworkingcopies'] # noqa if not self.canExecute(rule, req): return True # cut out early, we can't do this event data = { 'info': '' } if IPloneFormGenField.providedBy(obj): # if ploneformgen field, use parent object for modified data data['field'] = obj.getId() obj = aq_parent(obj) # the order of those interface checks matters since some interfaces # inherit from others if IObjectRemovedEvent.providedBy(event): # need to keep track of removed events so it doesn't get called # more than once for each object action = 'removed' elif (IObjectInitializedEvent.providedBy(event) or IObjectCreatedEvent.providedBy(event) or IObjectAddedEvent.providedBy(event)): action = 'added' elif IObjectMovedEvent.providedBy(event): # moves can also be renames. Check the parent object if event.oldParent == event.newParent: if rule is None or 'Rename' in rule.rule.title: info = {'previous_id': event.oldName} data['info'] = json.dumps(info) action = 'rename' else: # cut out here, double action for this event return True else: if rule is None or 'Moved' in rule.rule.title: parent_path = '/'.join(event.oldParent.getPhysicalPath()) previous_location = parent_path + '/' + event.oldName info = {'previous_location': previous_location} data['info'] = json.dumps(info) action = 'moved' else: # step out immediately since this could be a double action return True elif IObjectModifiedEvent.providedBy(event): action = 'modified' elif IActionSucceededEvent.providedBy(event): info = {'transition': event.action, 'comments': self.get_history_comment()} data['info'] = json.dumps(info) action = 'workflow' elif IObjectClonedEvent.providedBy(event): action = 'copied' elif ICheckinEvent.providedBy(event): info = {'message': event.message} data['info'] = json.dumps(info) action = 'checked in' req.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline elif IBeforeCheckoutEvent.providedBy(event): action = 'checked out' req.environ['disable.auditlog'] = True elif ICancelCheckoutEvent.providedBy(event): action = 'cancel check out' req.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline elif IUserLoggedInEvent.providedBy(event): action = 'logged in' info = {'user': event.object.getUserName()} data['info'] = json.dumps(info) elif IUserLoggedOutEvent.providedBy(event): action = 'logged out' else: logger.warn('no action matched') return True if IWorkingCopy.providedBy(obj): # if working copy, iterate, check if Track Working Copies is # enabled if trackWorkingCopies: # if enabled in control panel, use original object and move # working copy path to working_copy data['working_copy'] = '/'.join(obj.getPhysicalPath()) relationships = obj.getReferences( WorkingCopyRelation.relationship) # check relationships, if none, something is wrong, not logging # action if len(relationships) > 0: obj = relationships[0] else: return True else: # if not enabled, we only care about checked messages if 'check' not in action: return True data.update(getObjectInfo(obj)) data['action'] = action addLogEntry(obj, data) return True