# HG changeset patch # User Thierry Florac # Date 1429516274 -7200 # Node ID c422e7f61f19bd653c65e07898c58b458be55da7 # Parent 5b6650d040c2e9446312535bae3b5c144a3d6752 Added permissions widgets diff -r 5b6650d040c2 -r c422e7f61f19 src/pyams_security/widget/__init__.py --- a/src/pyams_security/widget/__init__.py Mon Apr 20 09:50:51 2015 +0200 +++ b/src/pyams_security/widget/__init__.py Mon Apr 20 09:51:14 2015 +0200 @@ -18,15 +18,18 @@ # import interfaces from pyams_form.interfaces.form import IFormLayer -from pyams_security.interfaces import ISecurityManager -from pyams_security.schema import IPrincipal, IPrincipalsSet -from pyams_security.widget.interfaces import IPrincipalWidget, IPrincipalsSetWidget -from z3c.form.interfaces import IDataConverter, IFieldWidget +from pyams_security.interfaces import ISecurityManager, IPermission +from pyams_security.schema import IPrincipal, IPrincipalsSet, IPermissionField, IPermissionsSetField +from pyams_security.widget.interfaces import IPrincipalWidget, IPrincipalsSetWidget, IPermissionWidget, \ + IPermissionsSetWidget +from z3c.form.interfaces import IDataConverter, IFieldWidget, NO_VALUE +from zope.schema.interfaces import ITitledTokenizedTerm # import packages from pyams_form.widget import widgettemplate_config from pyams_utils.adapter import adapter_config -from pyams_utils.registry import query_utility +from pyams_utils.registry import query_utility, get_all_utilities_registered_for, get_utilities_for +from z3c.form.browser.select import SelectWidget from z3c.form.browser.widget import HTMLInputWidget from z3c.form.converter import BaseDataConverter from z3c.form.widget import Widget, FieldWidget @@ -34,6 +37,148 @@ # +# Permission widget +# + +@adapter_config(context=(IPermissionField, IPermissionWidget), provides=IDataConverter) +class PermissionDataConverter(BaseDataConverter): + """Permission data converter""" + + def toWidgetValue(self, value): + # Permission widget is waiting for a Permission object + if not value: + return None + return query_utility(IPermission, name=value) + + def toFieldValue(self, value): + # Permission widget only returns selected permission ID + return value + + +@widgettemplate_config(mode='input', template='templates/permission-input.pt', layer=IFormLayer) +@widgettemplate_config(mode='display', template='templates/permission-display.pt', layer=IFormLayer) +@implementer_only(IPermissionWidget) +class PermissionWidget(SelectWidget): + """Principal widget""" + + def isSelected(self, term): + return term.token == self.value.id + + def items(self): + if self.terms is None: # update() has not been called yet + return () + items = [] + if (not self.required or self.prompt) and self.multiple is None: + message = self.noValueMessage + if self.prompt: + message = self.promptMessage + items.append({'id': self.id + '-novalue', + 'value': self.noValueToken, + 'content': message, + 'selected': self.value == []}) + + ignored = {self.value.id} if self.value else set() + + def addItem(idx, term, prefix=''): + selected = self.isSelected(term) + if selected and term.token in ignored: + ignored.remove(term.token) + id = '%s-%s%i' % (self.id, prefix, idx) + content = term.token + if ITitledTokenizedTerm.providedBy(term): + content = self.request.localizer.translate(term.title) + items.append({'id': id, 'value': term.token, 'content': content, 'selected': selected}) + + for idx, term in enumerate(self.terms): + addItem(idx, term) + + if ignored: + # some values are not displayed, probably they went away from the vocabulary + for idx, token in enumerate(sorted(ignored)): + try: + term = self.terms.getTermByToken(token) + except LookupError: + # just in case the term really went away + continue + + addItem(idx, term, prefix='missing-') + return items + + @property + def value_map(self): + if not self.value: + return '' + translate = self.request.localizer.translate + return json.dumps({self.value.id: translate(self.value.title)}) + + def extract(self, default=NO_VALUE): + result = super(PermissionWidget, self).extract(default) + if result != default: + result = result[0] + return result + + +@adapter_config(context=(IPermissionField, IFormLayer), provides=IFieldWidget) +def PermissionFieldWidget(field, request): + """Permission field widget factory""" + return FieldWidget(field, PermissionWidget(request)) + + +# +# Permissions set widget +# + +@adapter_config(context=(IPermissionsSetField, IPermissionsSetWidget), provides=IDataConverter) +class PermissionsSetDataConverter(BaseDataConverter): + """Permissions set data converter""" + + def toWidgetValue(self, value): + # Permissions set widget is waiting for a set of Permission object + if not value: + return () + return sorted((query_utility(IPermission, name=permission_id) for permission_id in value), + key=lambda x: x.title) + + def toFieldValue(self, value): + # Permissions set widget only returns selected permissions IDs in a single input + if not value: + return set() + return set(value.split('|')) + + +@widgettemplate_config(mode='input', template='templates/permissions-set-input.pt', layer=IFormLayer) +@widgettemplate_config(mode='display', template='templates/permissions-set-display.pt', layer=IFormLayer) +@implementer_only(IPermissionsSetWidget) +class PermissionsSetWidget(HTMLInputWidget, Widget): + """Permissions set widget""" + + @property + def values_data(self): + translate = self.request.localizer.translate + registry = self.request.registry + return json.dumps(sorted([{'id': permission.id, 'text': translate(permission.title)} + for name, permission in registry.getUtilitiesFor(IPermission)], + key=lambda x: x['text'])) + + @property + def values_str(self): + return '|'.join((permission.id for permission in (self.value or ()))) + + @property + def values_map(self): + result = {} + translate = self.request.localizer.translate + [result.update({value.id: translate(value.title)}) for value in (self.value or ())] + return json.dumps(result) + + +@adapter_config(context=(IPermissionsSetField, IFormLayer), provides=IFieldWidget) +def PermissionsSetFieldWidget(field, request): + """Permissions set field widget factory""" + return FieldWidget(field, PermissionsSetWidget(request)) + + +# # Principal widget # diff -r 5b6650d040c2 -r c422e7f61f19 src/pyams_security/widget/interfaces.py --- a/src/pyams_security/widget/interfaces.py Mon Apr 20 09:50:51 2015 +0200 +++ b/src/pyams_security/widget/interfaces.py Mon Apr 20 09:51:14 2015 +0200 @@ -21,6 +21,14 @@ # import packages +class IPermissionWidget(IWidget): + """Permission widget""" + + +class IPermissionsSetWidget(IWidget): + """Permissions set widget""" + + class IPrincipalWidget(IWidget): """Principal widget""" diff -r 5b6650d040c2 -r c422e7f61f19 src/pyams_security/widget/templates/permission-display.pt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_security/widget/templates/permission-display.pt Mon Apr 20 09:51:14 2015 +0200 @@ -0,0 +1,24 @@ + diff -r 5b6650d040c2 -r c422e7f61f19 src/pyams_security/widget/templates/permission-input.pt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_security/widget/templates/permission-input.pt Mon Apr 20 09:51:14 2015 +0200 @@ -0,0 +1,40 @@ + diff -r 5b6650d040c2 -r c422e7f61f19 src/pyams_security/widget/templates/permissions-set-display.pt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_security/widget/templates/permissions-set-display.pt Mon Apr 20 09:51:14 2015 +0200 @@ -0,0 +1,26 @@ + diff -r 5b6650d040c2 -r c422e7f61f19 src/pyams_security/widget/templates/permissions-set-input.pt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_security/widget/templates/permissions-set-input.pt Mon Apr 20 09:51:14 2015 +0200 @@ -0,0 +1,44 @@ +