diff --git a/.gitignore b/.gitignore index a98b50f64..48749d614 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ export/ /package.json /watch-run.py /watchable-grunt.js +cache/ diff --git a/castle/cms/_scripts/events-audit.py b/castle/cms/_scripts/events-audit.py new file mode 100644 index 000000000..6271c0bd2 --- /dev/null +++ b/castle/cms/_scripts/events-audit.py @@ -0,0 +1,39 @@ +import argparse +import logging +import os +import time + +from castle.cms.audit import _record +from castle.cms.constants import AUDIT_CACHE_DIRECTORY +from castle.cms.utils import ESConnectionFactoryFactory +from diskcache import Cache + + +logger = logging.getLogger(__name__) + +parser = argparse.ArgumentParser( + description='...') +parser.add_argument('--site-id', dest='site_id', default='Plone') +parser.add_argument('--cache-dir', dest='cache_dir', default=AUDIT_CACHE_DIRECTORY) +args, _ = parser.parse_known_args() + +site = app[args.site_id] +cache_dir = os.path.relpath(args.cache_dir) +registry = site.portal_registry +conn_factory = ESConnectionFactoryFactory(registry) + +while (True): + cache = Cache(cache_dir) + if len(cache) == 0: + cache.close() + time.sleep(30) + else: + with Cache(cache.directory) as reference: + for key in reference: + args = (conn_factory, reference[key]['site_path'], reference[key]['data']) + kwargs = reference[key]['kwargs'] + try: + _record(*args, **kwargs) + del reference[key] + except: + logger.error('could not add record to audit log') diff --git a/castle/cms/audit.py b/castle/cms/audit.py index 0a4154778..0de763379 100644 --- a/castle/cms/audit.py +++ b/castle/cms/audit.py @@ -29,6 +29,10 @@ import os +from castle.cms.events import (ICacheInvalidatedEvent, + IMetaTileEditedEvent, + ITrashEmptiedEvent) +from castle.cms.interfaces import ITrashed from plone import api from plone.app.iterate.interfaces import IAfterCheckinEvent from plone.app.iterate.interfaces import ICancelCheckoutEvent @@ -55,12 +59,6 @@ from zope.lifecycleevent.interfaces import IObjectRemovedEvent -from castle.cms.events import ICacheInvalidatedEvent -from castle.cms.events import IMetaTileEditedEvent -from castle.cms.events import ITrashEmptiedEvent -from castle.cms.interfaces import ITrashed - - logger = logging.getLogger("Plone") DEFAULT_AUDIT_LOGGER_CONFIG = { diff --git a/castle/cms/constants.py b/castle/cms/constants.py index 53e41d415..b535aaa4e 100644 --- a/castle/cms/constants.py +++ b/castle/cms/constants.py @@ -27,3 +27,4 @@ VALID_CSS_FONT_SIZE_PATTERN = compile("^\s*\d+\s*({})\s*$".format( # noqa:W605 '|'.join(ABSOLUTE_FONT_UNITS) )) +AUDIT_CACHE_DIRECTORY = 'cache/auditcache' diff --git a/castle/cms/tests/test_audit.py b/castle/cms/tests/test_audit.py new file mode 100644 index 000000000..d78274460 --- /dev/null +++ b/castle/cms/tests/test_audit.py @@ -0,0 +1,47 @@ +import unittest + +from castle.cms.constants import AUDIT_CACHE_DIRECTORY +from castle.cms.testing import CASTLE_PLONE_INTEGRATION_TESTING +from diskcache import Cache +from plone import api +from plone.app.testing import TEST_USER_ID +from plone.app.testing import TEST_USER_NAME +from plone.app.testing import login +from plone.app.testing import setRoles + + +class TestAudit(unittest.TestCase): + + layer = CASTLE_PLONE_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] + self.request = self.layer['request'] + login(self.portal, TEST_USER_NAME) + setRoles(self.portal, TEST_USER_ID, ('Member', 'Manager')) + api.portal.set_registry_record( + 'collective.elasticsearch.interfaces.IElasticSettings.enabled', True) + + def test_cache_object(self): + obj = api.content.create(type='Document', id='doc1', + container=self.portal) + api.content.transition(obj=obj, to_state='published') + obj.reindexObject() + obj_id = getattr(obj, '_plone.uuid') + cache = Cache(AUDIT_CACHE_DIRECTORY) + self.assertTrue(obj_id in cache) + cache.clear() + + def test_es_custom_index(self): + obj = api.content.create(type='Document', id='doc1', + container=self.portal) + api.portal.set_registry_record('castle.es_index_enabled', True) + api.portal.set_registry_record('castle.es_index', u'test-index') + api.content.transition(obj=obj, to_state='published') + obj.reindexObject() + obj_id = getattr(obj, '_plone.uuid') + cache = Cache(AUDIT_CACHE_DIRECTORY) + self.assertTrue(obj_id in cache) + self.assertTrue(cache[obj_id]['kwargs']['es_custom_index_name_enabled']) + self.assertEqual(cache[obj_id]['kwargs']['custom_index_value'], u'test-index') + cache.clear() diff --git a/setup.py b/setup.py index 2202259be..8ae10bcdf 100644 --- a/setup.py +++ b/setup.py @@ -86,6 +86,7 @@ def read(*rnames): 'tendo', 'pylru', 'sqlalchemy', + 'diskcache', # misc 'z3c.unconfigure', diff --git a/versions.cfg b/versions.cfg index 99cc9ea24..1a801e5b8 100644 --- a/versions.cfg +++ b/versions.cfg @@ -110,6 +110,7 @@ futures = 3.3.0 jmespath = 0.9.4 s3transfer = 0.2.1 pylru = 1.2.0 +diskcache = 4.1.0 configparser = 4.0.2 zipp = 1.2.0