Skip to content

Instantly share code, notes, and snippets.

@zopyx
Created April 26, 2017 07:49
Show Gist options
  • Save zopyx/c330f8abf5bbaaddf4fd8e30062af894 to your computer and use it in GitHub Desktop.
Save zopyx/c330f8abf5bbaaddf4fd8e30062af894 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
from plone.autoform import directives
from plone.dexterity.content import Item
from plone.formwidget.autocomplete.widget import AutocompleteSelectionWidget # noqa
from Products.CMFPlone.utils import safe_unicode
from unimr.staff.i18n import MessageFactory as _
from unimr.staff.interfaces import IStaffService
from z3c.formwidget.query.interfaces import IQuerySource
from zope import schema
from zope.component import getUtility
from zope.interface import implementer
from zope.interface import Interface
from zope.schema.interfaces import IContextSourceBinder
from zope.schema.vocabulary import SimpleTerm
from zope.schema.vocabulary import SimpleVocabulary
import base64
import z3c.form
class LdapAutocompleteSelectionWidget(AutocompleteSelectionWidget):
"""
Customize AutocompleteSelectionWidget to increase maxResults and minChars
"""
minChars = 3
maxResults = 30
@implementer(z3c.form.interfaces.IFieldWidget)
def LdapAutocompleteFieldWidget(field, request): # noqa
return z3c.form.widget.FieldWidget(
field, LdapAutocompleteSelectionWidget(request))
@implementer(IQuerySource)
class LdapKeywordSource(object):
def __init__(self, context):
self.vocab = SimpleVocabulary([])
self.context = context
def __contains__(self, term):
# return True, to actually ignoreMissing
return True
def __iter__(self):
return self.vocab.__iter__()
def __len__(self):
return self.vocab.__len__()
def getTerm(self, value): # noqa
# return fake term, to actually ignoreMissing
return SimpleTerm(value)
def getTermByToken(self, value): # noqa
# return fake term, to actually ignoreMissing
return SimpleTerm(value)
def search(self, query_string=None):
if not query_string:
return self.vocab
q = query_string.lower()
ldap_service = getUtility(IStaffService)
all_depts = ldap_service.get_departments_as_dict()
result = list()
for dn, dept in all_depts.items():
if dept['normalized']:
continue
if q in dept['title'].lower():
short_dn = dn.replace(u'ou=', u'').replace(u'c=', u'')
title = u'{0} ({1})'.format(safe_unicode(dept['title']), short_dn)
# We need a unique ASCII token for the DN (which is unicode).
# The encoding process is completely random and could be replaced
# with something more sane..but the token must be ASCII
token = base64.encodestring(dn.encode('utf8')).replace('\n', '#')
result.append(SimpleTerm(value=dn, token=token, title=title))
self.vocab = SimpleVocabulary(result)
return result
@implementer(IContextSourceBinder)
class LdapKeywordSourceBinder(object):
def __call__(self, context):
return LdapKeywordSource(context)
class IStaffListing(Interface):
directives.widget('basedn_encoded', LdapAutocompleteFieldWidget)
basedn_encoded = schema.Choice(
title=_(u'LDAP DN Department'),
source=LdapKeywordSourceBinder(),
default=u'',
required=True
)
ldap_roles_filter = schema.List(
title=_(u'LDAP roles filter'),
required=True,
value_type=schema.Choice(
title=u'Roles',
vocabulary='unimr.staff.roles',
required=False),
)
ldap_filter = schema.TextLine(
title=_(u'Generic LDAP filter'),
required=False)
@implementer(IStaffListing)
class StaffListing(Item):
"""StaffListing content object"""
@property
def basedn(self):
return unicode(base64.decodestring(
self.basedn_encoded.replace('#', '\n')), 'utf8')
0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment