Skip to content

Commit

Permalink
Allow to disable global Auditlogging (senaite#2074)
Browse files Browse the repository at this point in the history
* Patched catalog_object method

* Added schema fields in senaite_setup

* Hide setup tile when auditlogging is disabled

* Added proxy fields in bika_setup

* Changelog updated

* Update src/bika/lims/content/bikasetup.py

Co-authored-by: Winnie <winniehell@users.noreply.github.com>

* Show status message when auditlog is disabled

Co-authored-by: Winnie <winniehell@users.noreply.github.com>
  • Loading branch information
ramonski and winniehell authored Jul 28, 2022
1 parent b4f47e1 commit fa5b48b
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Changelog
2.3.0 (unreleased)
------------------

- #2074 Allow to disable global Auditlogging
- #2072 Refactor report filename generation to own method
- #2071 Move sample reports to report catalog, add batch ID and email sent flag to listing
- #2070 Fix typo/duplicate translation key in colophon
Expand Down
32 changes: 32 additions & 0 deletions src/bika/lims/content/bikasetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,21 @@ def getCounterTypes(self, instance=None):
"this option will be checked and readonly.")
)
),
# NOTE: This is a Proxy Field which delegates to the SENAITE Registry!
BooleanField(
"EnableGlobalAuditlog",
schemata="Security",
default=False,
widget=BooleanWidget(
label=_("Enable global Audit Log"),
description=_(
"The global Auditlog shows all modifications of the system. "
"When enabled, all entities will be indexed in a separate "
"catalog. This will increase the time when objects are "
"created or modified."
)
)
),
BooleanField(
'ShowPrices',
schemata="Accounting",
Expand Down Expand Up @@ -1001,5 +1016,22 @@ def setEmailBodySamplePublication(self, value):
if setup:
setup.setEmailBodySamplePublication(value)

def getEnableGlobalAuditlog(self):
"""Get the value from the senaite setup
"""
setup = api.get_senaite_setup()
# setup is `None` during initial site content structure installation
if setup:
return setup.getEnableGlobalAuditlog()
return False

def setEnableGlobalAuditlog(self, value):
"""Set the value in the senaite setup
"""
setup = api.get_senaite_setup()
# setup is `None` during initial site content structure installation
if setup:
setup.setEnableGlobalAuditlog(value)


registerType(BikaSetup, PROJECTNAME)
42 changes: 42 additions & 0 deletions src/senaite/core/browser/viewlets/auditlog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-

from bika.lims import api
from plone.app.layout.viewlets import ViewletBase
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile


class AuditlogDisabledViewlet(ViewletBase):
"""Viewlet that is displayed when the Auditlog is disabled
"""
template = ViewPageTemplateFile("templates/auditlog_disabled.pt")

def __init__(self, context, request, view, manager=None):
super(AuditlogDisabledViewlet, self).__init__(
context, request, view, manager=manager)
self.context = context
self.request = request
self.view = view

@property
def setup(self):
return api.get_setup()

def get_setup_url(self):
"""Return the absolute URL of the setup
"""
return api.get_url(self.setup)

def is_enabled(self):
"""Returns whether the global auditlog is disabled
"""
return self.setup.getEnableGlobalAuditlog()

def is_disabled(self):
"""Returns whether the global auditlog is disabled
"""
return not self.is_enabled()

def index(self):
if self.is_enabled():
return ""
return self.template()
10 changes: 10 additions & 0 deletions src/senaite/core/browser/viewlets/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -328,4 +328,14 @@
permission="zope2.View"
layer="senaite.core.interfaces.ISenaiteCore" />

<!-- Auditlog viewlet -->
<browser:viewlet
for="bika.lims.interfaces.IAuditLog"
name="auditlog_disabled"
class=".auditlog.AuditlogDisabledViewlet"
manager="plone.app.layout.viewlets.interfaces.IAboveContent"
template="templates/auditlog_disabled.pt"
permission="zope2.View"
layer="senaite.core.interfaces.ISenaiteCore" />

</configure>
22 changes: 22 additions & 0 deletions src/senaite/core/browser/viewlets/templates/auditlog_disabled.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div tal:omit-tag=""
tal:condition="python:view.is_disabled()"
i18n:domain="senaite.core">

<div id="portal-alert">
<div class="portlet-alert-item alert alert-warning alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<p class="title">
<strong i18n:translate="">
Global Audit Log is disabled
</strong>
</p>
<p class="description" i18n:translate="">
You can enable the global Audit Log again in the
<a href="#" tal:attributes="href python:view.get_setup_url()">Setup</a>
</p>
</div>
</div>

</div>
35 changes: 33 additions & 2 deletions src/senaite/core/content/senaitesetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

from AccessControl import ClassSecurityInfo
from bika.lims import api
from plone.app.textfield import IRichTextValue
from plone.app.textfield.widget import RichTextFieldWidget # TBD: port to core
from plone.autoform import directives
from plone.supermodel import model
from plone.app.textfield.widget import RichTextFieldWidget # TBD: port to core
from plone.app.textfield import IRichTextValue
from Products.CMFCore import permissions
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from senaite.core.catalog import AUDITLOG_CATALOG
from senaite.core.content.base import Container
from senaite.core.interfaces import IHideActionsMenu
from senaite.core.interfaces import ISetup
from senaite.core.schema import RichTextField
from senaite.impress import senaiteMessageFactory as _
from zope import schema
from zope.interface import implementer
from zope.interface import provider
from zope.schema.interfaces import IContextAwareDefaultFactory
Expand Down Expand Up @@ -44,6 +46,17 @@ class ISetupSchema(model.Schema):
required=False,
)

enable_global_auditlog = schema.Bool(
title=_(u"Enable global Auditlog"),
description=_(
"The global Auditlog shows all modifications of the system. "
"When enabled, all entities will be indexed in a separate "
"catalog. This will increase the time when objects are "
"created or modified."
),
default=False,
)

###
# Fieldsets
###
Expand Down Expand Up @@ -83,3 +96,21 @@ def setEmailBodySamplePublication(self, value):
"""
mutator = self.mutator("email_body_sample_publication")
return mutator(self, value)

@security.protected(permissions.View)
def getEnableGlobalAuditlog(self):
"""Returns if the global Auditlog is enabled
"""
accessor = self.accessor("enable_global_auditlog")
return accessor(self)

@security.protected(permissions.ModifyPortalContent)
def setEnableGlobalAuditlog(self, value):
"""Enable/Disable global Auditlogging
"""
if value is False:
# clear the auditlog catalog
catalog = api.get_tool(AUDITLOG_CATALOG)
catalog.manage_catalogClear()
mutator = self.mutator("enable_global_auditlog")
return mutator(self, value)
13 changes: 13 additions & 0 deletions src/senaite/core/patches/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,29 @@
from bika.lims import api
from plone.indexer.interfaces import IIndexableObject
from Products.ZCatalog.ZCatalog import ZCatalog
from senaite.core.catalog import AUDITLOG_CATALOG
from zope.component import queryMultiAdapter


def is_auditlog_enabled():
setup = api.get_senaite_setup()
if not setup:
return False
return setup.getEnableGlobalAuditlog()


def catalog_object(self, object, uid=None, idxs=None,
update_metadata=1, pghandler=None):

# Never catalog temporary objects
if api.is_temporary(object):
return

# skip indexing auditlog catalog if disabled
if self.id == AUDITLOG_CATALOG:
if not is_auditlog_enabled():
return

if idxs is None:
idxs = []
self._increment_counter()
Expand Down

0 comments on commit fa5b48b

Please sign in to comment.