Source code for extools.ui.field_security

"""Field Security UIs

UIs for implementing additional security at the field level.

Use the :py:meth:`extools.ui.field_security.permissions_callback_for_table`
together with the :py:class:`extools.ui.field_security.FieldSecurityCallbackUI`
to quickly apply permissions to pretty much any field on a Sage screen.

.. code-block:: python

    # AP1200
    # Add permissions to AP Vendor Tax Number field

    MY_PERMISSIONS_TABLE = "MYMODULE.MYPERMS"
    '''Table format
    | USER | CANREAD | CANWRITE |'''

    # The tax number field control name from accpacUIInfo
    TAX_NUM_CONTROL = "afecAPVENtaxnbr"
    # The tab control name
    TAB_CONTROL = "SSTab1"
    # The id of the "Invoicing" tab, which has the field.
    TAB_ID = 1

    def main(*args, **kwargs):
        callback = permissions_callback_for_table(
                MY_PERMISSIONS_TABLE, "USER", "CANREAD", "CANWRITE")
        ui = FieldSecurityCallbackUI(
                TAX_NUM_CONTROL, callback, TAB_CONTROL, TAB_ID)
"""
try:
    from accpac import *
except ImportError:
    UI = object

from extools.view import exview
from extools.view.errors import ExViewRecordDoesNotExist

[docs]def permissions_callback_for_table(view, user_field, read_field, write_field): """Generate a callback that checks a user's permissions in a view. Best used with the :py:class:`FieldSecurityCallbackUI`, it will check a table containing permissions and return a simple (read, write) pair suitable for use as a callback. :param view: the view to read from, built-in (OE0520) or custom (MOD.TABLE) :type view: str :param user_field: the username field in the view. must be a key or browseable field. :type user_field: str :param read_field: the read permission field name - must be bool. :type read_field: str :param write_field: the write permission field name - must be bool. :type write_field: str :returns: func """ def check_permissions(user, control, ds, *args, **kwargs): try: with exview(view, seek_to={user_field: user}) as exv: read = bool(int(exv.get(read_field))) write = bool(int(exv.get(write_field))) return (read, write) except ExViewRecordDoesNotExist: pass except (ValueError, TypeError): pass return (False, False) return check_permissions
[docs]class FieldSecurityCallbackUI(UI): """Apply custom permissions to a specific on-screen field. :param control: name of the on-screen control. :type control: str :param callback: callback function to check perms. receives (user, control, ds). callback must return (bool(can_read), bool(can_write)). :type callback: func :param tab_control: name of the tab control (if applicable). :type tab_control: str :param tab_id: tab id on which the field appears (if applicable). :type tab_id: str :param ds_name: name of a ds (i.e. adsOEORDH) to open and pass to callback. :type ds_name: str """ def __init__(self, control, callback, tab_control="", tab_id=None, ds_name=""): UI.__init__(self) self.control = control self.callback = callback self.tab_control = tab_control self.tab_id = tab_id self.ds = None self.ds_name = ds_name self.getControlInfo(control, self.onControlInfo) self.show()
[docs] def onControlInfo(self, info): # Get the host control. self.field = self.getHostControl(self.control) if self.ds_name: self.ds = openDataSource(self.ds_name) if self.tab_control: self.tabs = self.getHostControl(self.tab_control) self.tabs.setOnClick(self.onTabClick) self._apply_permissions()
def _apply_permissions(self): r, w = self.callback(self.control, self.ds) if r: if w: self.field.enable() else: self.field.disable() else: self.field.hide()
[docs] def onTabClick(self, tab): """On tab change hide or show field based on callback.""" if tab == self.tab_id: if hasattr(self, 'field'): self._apply_permissions()