Advertisement
Guest User

Untitled

a guest
Jul 18th, 2017
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.78 KB | None | 0 0
  1. """
  2. plugin.py
  3. ---------
  4. PAS plugin for dealing with ERC users
  5. Modified by Ruben Hidalgo - Drago: 2010-11
  6. """
  7.  
  8. import sys
  9. import copy
  10. import md5
  11. import base64
  12. import urllib
  13. import logging
  14.  
  15. from Globals import InitializeClass
  16. from OFS.Cache import Cacheable
  17. from DateTime import DateTime
  18. from AccessControl import ClassSecurityInfo
  19. from Products.PageTemplates.PageTemplateFile import PageTemplateFile
  20. from persistent.dict import PersistentDict
  21. import zope.event
  22.  
  23. from Products.CMFCore.utils import getToolByName
  24. from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
  25. from Products.PluggableAuthService.utils import classImplements
  26. from Products.PluggableAuthService.interfaces.plugins import (
  27. IAuthenticationPlugin, IRolesPlugin, IUserEnumerationPlugin,
  28. ICredentialsUpdatePlugin, ICredentialsResetPlugin,
  29. IExtractionPlugin)
  30. from Products.PlonePAS.interfaces.plugins import IUserManagement
  31.  
  32. from exception import ERCException, ERCDeactivatedUserException
  33. import erc
  34. import ercmock
  35. import events
  36.  
  37. manage_addErcAuthPluginForm = PageTemplateFile(
  38. 'www/add', globals(), __name__='manage_addErcAuthPluginForm')
  39.  
  40. erc_pas_plugin_form_fields = [
  41. ('erc_protocol', ('ERC Protocol', True, 'https')),
  42. ('erc_hostname', ('ERC Hostname', True, 'testservice.lillyerc.eu')),
  43. ('erc_port', ('ERC Port', True, '443')),
  44. ('erc_path', ('ERC Path', True, 'ERCService')),
  45. ('erc_subsite', ('ERC Subsite', True, '')),
  46. ('erc_view_name', ('ERC view name', True, 'view_contact_es')),
  47. ('view_sr_by_prod', ('ERC VIEW_SR_BY_PROD', True, 'VIEW_SR_BY_PROD_IT')),
  48. ('view_pim_seg', ('ERC VIEW_PIM_SEG', True, 'VIEW_PIM_SEG')),
  49. ('view_campaign', ('ERC VIEW_CAMPAIGN', True, 'VIEW_CAMPAIGN')),
  50. ('enable_cegedim', ('Enable cegedim', True, False)),
  51. ('role_mapper_func', ('Role mapper function', True, 'drago.ercpas.plugin.role_mapper')),
  52. ]
  53.  
  54. def activate_all_interfaces(dispatcher, plugin):
  55. interfaces = []
  56. for info in dispatcher.plugins.listPluginTypeInfo():
  57. if plugin.testImplements(info['interface']):
  58. interfaces.append(info['id'])
  59. plugin.manage_activateInterfaces(interfaces)
  60.  
  61. def manage_addErcAuthPlugin(dispatcher, id, erc_protocol,
  62. erc_hostname, erc_port, erc_path, erc_subsite, erc_view_name,
  63. view_sr_by_prod, view_pim_seg, view_campaign, enable_cegedim,
  64. role_mapper_func, title=None, REQUEST=None):
  65. """ Add a ErcAuthPlugin to a Pluggable Auth Service. """
  66.  
  67. environ = {
  68. 'erc_protocol': erc_protocol,
  69. 'erc_hostname': erc_hostname,
  70. 'erc_port': erc_port,
  71. 'erc_path': erc_path,
  72. 'erc_subsite': erc_subsite,
  73. 'erc_view_name': erc_view_name,
  74. 'view_sr_by_prod': view_sr_by_prod,
  75. 'view_pim_seg': view_pim_seg,
  76. 'view_campaign': view_campaign,
  77. 'enable_cegedim': enable_cegedim,
  78. }
  79.  
  80. obj = ErcAuthPlugin(id, title, environ, None, role_mapper_func)
  81. dispatcher._setObject(obj.getId(), obj)
  82. obj = getattr(dispatcher, obj.getId())
  83. activate_all_interfaces(dispatcher, obj)
  84.  
  85. if REQUEST is not None:
  86. REQUEST['RESPONSE'].redirect(
  87. '%s/manage_workspace'
  88. '?manage_tabs_message='
  89. 'ErcAuthPlugin+added.'
  90. % dispatcher.absolute_url())
  91.  
  92. def role_mapper(member_info):
  93. if member_info.get('userTypeId') == '1':
  94. return ('Psichiatra',)
  95.  
  96. elif member_info.get('userTypeId') == '2':
  97. return ('Psicologo',)
  98.  
  99. elif member_info.get('userTypeId') == '3':
  100. return ('Superuser',)
  101.  
  102. elif member_info.get('userTypeId') == '4':
  103. return ('Infermiere',)
  104.  
  105. elif member_info.get('userTypeId') == '5':
  106. return ('Educatoreprofessionale',)
  107.  
  108. elif member_info.get('userTypeId') == '6':
  109. return ('Tecnicodellariabilitazionepsichiatrica',)
  110.  
  111. elif member_info.get('userTypeId') == '7':
  112. return ('Altro',)
  113.  
  114.  
  115. class ErcAuthPlugin(BasePlugin, Cacheable):
  116.  
  117. """ ERC Auth Plugin
  118. """
  119.  
  120. meta_type = 'Erc Auth Plugin'
  121. cookie_name = '__ac'
  122. path = '/'
  123.  
  124. security = ClassSecurityInfo()
  125.  
  126. def __init__(self, id, title, erc_environ, erc_namemap, role_mapper_func=None):
  127. self._id = self.id = id
  128. self.title = title
  129. if role_mapper_func:
  130. self.addRoleMapper(role_mapper_func)
  131. else:
  132. self.roleMapperFunc = 'drago.ercpas.plugin.role_mapper'
  133. self.erc_environ = PersistentDict(erc_environ)
  134. self.erc = erc.Erc(environ=erc_environ, namemap=erc_namemap)
  135. self.erc_namemap = PersistentDict(self.erc.namemap)
  136.  
  137. # forms for ZMI
  138. manage_options = (
  139. {
  140. 'label': 'Configure',
  141. 'action': 'manage_configureErcAuthPluginForm'
  142. },
  143. {
  144. 'label': 'Name map',
  145. 'action': 'manage_configureErcNameMapForm',
  146. },
  147. ) + BasePlugin.manage_options
  148.  
  149. manage_configureErcAuthPluginForm = PageTemplateFile(
  150. 'www/configure', globals(),
  151. __name__='manage_configureErcAuthPluginForm')
  152.  
  153. def manage_configureErcAuthPlugin(self, erc_protocol, erc_hostname,
  154. erc_port, erc_path, erc_subsite, erc_view_name, view_sr_by_prod,
  155. view_pim_seg, view_campaign, enable_cegedim, role_mapper_func,
  156. REQUEST=None):
  157. """Configure ERC server used in this plugin"""
  158.  
  159. environ = {
  160. 'erc_protocol': erc_protocol,
  161. 'erc_hostname': erc_hostname,
  162. 'erc_port': erc_port,
  163. 'erc_path': erc_path,
  164. 'erc_subsite': erc_subsite,
  165. 'erc_view_name': erc_view_name,
  166. 'view_sr_by_prod': view_sr_by_prod,
  167. 'view_pim_seg': view_pim_seg,
  168. 'view_campaign': view_campaign,
  169. 'enable_cegedim': enable_cegedim,
  170. }
  171. self.erc_environ = PersistentDict(environ)
  172. self.erc.setup(environ)
  173. self.addRoleMapper(role_mapper_func)
  174. if REQUEST is not None:
  175. REQUEST['RESPONSE'].redirect((
  176. '%s/manage_configureErcAuthPluginForm?'
  177. 'manage_tabs_message=Settings+saved.'
  178. ) % self.absolute_url())
  179.  
  180. manage_configureErcNameMapForm = PageTemplateFile(
  181. 'www/namemap.zpt', globals(),
  182. __name__='manage_configureErcNameMapForm')
  183.  
  184. def manage_configureErcNameMap(self, REQUEST=None, **kwargs):
  185. """Configure the name map used for mapping erc properties to
  186. user properties"""
  187. if REQUEST is not None:
  188. if 'manage_configureErcNameMap' in REQUEST.form:
  189. del REQUEST.form['manage_configureErcNameMap']
  190. kwargs.update(REQUEST.form)
  191. self.erc_namemap = PersistentDict(kwargs)
  192. self.erc.namemap = kwargs
  193. if REQUEST is not None:
  194. REQUEST['RESPONSE'].redirect((
  195. '%s/manage_configureErcNameMapForm?'
  196. 'manage_tabs_message=Settings+saved.'
  197. ) % self.absolute_url())
  198.  
  199. def manage_deleteErcNameMapProperties(self, properties=None, REQUEST=None):
  200. """Delete some properties in the erc name map
  201.  
  202. :Parameters:
  203. - `properties`: a list of property ids to delete from the erc name map
  204. """
  205. if not properties:
  206. properties = []
  207. if REQUEST is not None:
  208. delete = REQUEST.form.get('delete')
  209. if not isinstance(delete, list):
  210. delete = [delete]
  211. properties.extend(delete)
  212. for p in properties:
  213. if p in self.erc_namemap:
  214. del self.erc_namemap[p]
  215. self.erc.namemap = dict(self.erc_namemap)
  216. if REQUEST is not None:
  217. REQUEST['RESPONSE'].redirect((
  218. '%s/manage_configureErcNameMapForm?'
  219. 'manage_tabs_message=Properties+deleted.'
  220. ) % self.absolute_url())
  221.  
  222. def manage_addErcNameMapProperty(self, id, value, REQUEST=None):
  223. """Add a new mapping into the name map"""
  224. self.erc_namemap.update({id: value})
  225. self.erc.namemap = dict(self.erc_namemap)
  226. if REQUEST is not None:
  227. REQUEST['RESPONSE'].redirect((
  228. '%s/manage_configureErcNameMapForm?'
  229. 'manage_tabs_message=Settings+saved.'
  230. ) % self.absolute_url())
  231. # end of forms for ZMI
  232.  
  233. def addRoleMapper(self, function):
  234. self.roleMapperFunc = function
  235. module, function = tuple(self.roleMapperFunc.rsplit('.', 1))
  236. if module not in sys.modules:
  237. __import__(module)
  238.  
  239. def roleMapper(self, memberInfo):
  240. module, function = tuple(self.roleMapperFunc.rsplit('.', 1))
  241. if module not in sys.modules:
  242. __import__(module)
  243. return getattr(sys.modules[module], function)(memberInfo)
  244.  
  245. def removeRoleMapper(self):
  246. self.roleMapperFunc = 'drago.ercpas.plugin.role_mapper'
  247.  
  248. # IAuthenticationPlugin implementation
  249. security.declarePrivate('authenticateCredentials')
  250. def authenticateCredentials(self, credentials):
  251. """ See IAuthenticationPlugin.
  252.  
  253. o We expect the credentials to be those returned by
  254. ILoginPasswordExtractionPlugin.
  255. """
  256. login = credentials.get('login')
  257. password = credentials.get('password')
  258. passwordHash = credentials.get('passwordHash')
  259. username = credentials.get('username')
  260. extractor = credentials.get('extractor')
  261. # extractor = 'erc_plugin'
  262.  
  263. if not username: username = login
  264.  
  265. # if the credentials are not extracted by this plugin, they
  266. # are for some other plugin, if there is no extractor, we
  267. # need to continue authenticating
  268. if extractor is not None and extractor != self.id:
  269. return
  270.  
  271. if not password and not passwordHash:
  272. return
  273.  
  274. if not passwordHash:
  275. try:
  276. # username, passwordHash = self.erc.emailLogin(login, password)
  277. username, passwordHash = self.erc.login(login, password)
  278. # except ERCDeactivatedUserException, e:
  279. except ERCDeactivatedUserException:
  280. return 'deactivated_user', 'deactivated_user'
  281.  
  282. if login is None or passwordHash is None:
  283. return
  284.  
  285. try:
  286. if not username:
  287. # username = self.erc.emailLoginMD5(login, passwordHash)
  288. username, passwordHash = self.erc.login(login, password)
  289. if username:
  290. self.REQUEST.SESSION.set('__ac_username', username)
  291. if not credentials.get('username'):
  292. # only set erc_id to current plugin if we actually
  293. # authenticated, not using just the username
  294. self.REQUEST.SESSION.set('erc_id', self.id)
  295. return login, login
  296. except ERCDeactivatedUserException, e:
  297. # catch a deactivated user exception - setting a custom username is the way to communicate to the UI
  298. # that the user is registered but is unable to authenticate becuase they are deactivated
  299. return 'deactivated_user', 'deactivated_user'
  300.  
  301. # IRolesPlugin implementation
  302. security.declarePrivate('getRolesForPrincipal')
  303. def getRolesForPrincipal(self, principal, request=None):
  304. if self.REQUEST.SESSION.get('erc_id') != self.id:
  305. print 'getRolesForPrincipal returns ()'
  306. return ()
  307.  
  308. pm = getToolByName(principal, 'portal_membership')
  309. campaignRoles = []
  310. # ... pretends getRolesForPrincipal only gets called with the
  311. # current logged in user
  312. memberInfo = pm._getErcInfoWithCache(principal) or {}
  313. campaigns = memberInfo.get('campaigns', {})
  314. for campaign in campaigns.values():
  315. if campaign.status.lower() != 'launched':
  316. continue
  317. if campaign.start and \
  318. not (campaign.start.isCurrentDay() or \
  319. campaign.start.isPast()):
  320. continue
  321. if campaign.end and \
  322. not (campaign.end.isCurrentDay() or \
  323. campaign.end.isFuture()):
  324. continue
  325. campaignRoles.append('Campaign%s' % campaign.campaign_id)
  326. baseRoles = self.roleMapper(memberInfo)
  327. # return baseRoles + tuple(campaignRoles)
  328. print 'getRolesForPrincipal returns %s' % baseRoles
  329. return baseRoles
  330.  
  331. # IUserEnumerationPlugin implementation
  332. security.declarePrivate( 'enumerateUsers' )
  333. def enumerateUsers( self
  334. , id=None
  335. , login=None
  336. , exact_match=False
  337. , sort_by=None
  338. , max_results=None
  339. , **kw
  340. ):
  341.  
  342. """ See IUserEnumerationPlugin.
  343. """
  344. user_info = []
  345. user_ids = []
  346.  
  347. terms = id or login
  348.  
  349. if exact_match:
  350. if not '@' in terms:
  351. # local user, don't mess with it
  352. return ()
  353. if terms:
  354. user_ids.extend([(terms, terms)])
  355. else:
  356. # insane - exact match with neither login nor id
  357. return ()
  358.  
  359. for user_id, login_id in user_ids:
  360. info = { 'id' : user_id,
  361. 'login' : login_id,
  362. 'pluginid' : self.getId()
  363. }
  364. user_info.append( info )
  365.  
  366. return tuple( user_info )
  367.  
  368. # ICredentialsUpdatePlugin implementation
  369. security.declarePrivate('updateCredentials')
  370. def updateCredentials(self, request, response, login, new_password):
  371. """ Respond to change of credentials. """
  372. #patch Karen III
  373. if not request.SESSION.get('erc_id') == self.id:
  374. # if '@' not in login:
  375. return
  376.  
  377. kw = {'path': '/'}
  378.  
  379. portal = self.portal_url.getPortalObject()
  380. domain_cookie = portal.getProperty('cookie_domain')
  381. if domain_cookie:
  382. kw['domain'] = domain_cookie
  383.  
  384. # (username, passwordHash) = self.erc.emailLogin(login, new_password)
  385. (username, passwordHash) = self.erc.login(login, new_password)
  386. expires = None
  387. if username:
  388. request.SESSION.set('__ac_username', username)
  389. #patch Karen III
  390. # request.SESSION.set('erc_id', self.id)
  391. portal = self.portal_url.getPortalObject()
  392. try:
  393. length = portal.getProperty('auth_cookie_length')
  394. length = int(length)
  395. except (AttributeError, ValueError, TypeError):
  396. length = 0
  397.  
  398. if length and self.REQUEST.form.get('__ac_persistent'):
  399. kw['expires'] = (DateTime() + length).toZone('GMT').rfc822()
  400. response.setCookie('__ac_persistent', 'True', **kw)
  401.  
  402. cookie_val = "%s %s" % (login.encode('hex'), passwordHash)
  403. cookie_val = urllib.quote(base64.encodestring(cookie_val))
  404. response.setCookie(self.cookie_name, cookie_val, **kw)
  405.  
  406. # ICredentialsResetPlugin implementation
  407. security.declarePrivate('resetCredentials')
  408. def resetCredentials(self, request, response):
  409. """ Empty out the currently-stored session values """
  410. kw = {}
  411.  
  412. response.expireCookie(self.cookie_name, path=self.path, **kw)
  413. response.expireCookie('__ac_persistent', path=self.path, **kw)
  414. self.REQUEST.SESSION.set('__ac_profile', None)
  415. self.REQUEST.SESSION.set('__ac_username', None)
  416. self.REQUEST.SESSION.set('erc_id', None)
  417.  
  418. def _extract_from_cookie(self, request, cookie):
  419. """Helper method to extract credentials from cookie"""
  420. creds = {}
  421. cookie_val = base64.decodestring(urllib.unquote(cookie))
  422. try:
  423. login, passwordHash = cookie_val.split(' ')
  424. except ValueError:
  425. # Cookie is in a different format, so it is not ours
  426. return creds
  427.  
  428. creds['login'] = login.decode('hex')
  429. creds['passwordHash'] = passwordHash
  430.  
  431. creds['username'] = request.SESSION.get('__ac_username')
  432.  
  433. if request.get('__ac_persistent'):
  434. self._set_persistent_cookie(request)
  435.  
  436. return creds
  437.  
  438. def _set_persistent_cookie(self, request):
  439. """ERC "remember me" """
  440. kw = {'path': '/'}
  441. portal = self.portal_url.getPortalObject()
  442. domain_cookie = portal.getProperty('cookie_domain')
  443. if domain_cookie:
  444. kw['domain'] = domain_cookie
  445. try:
  446. # update cookie expiry
  447. length = portal.getProperty('auth_cookie_length')
  448. length = int(length)
  449. kw['expires'] = (DateTime() + length).toZone('GMT').rfc822()
  450. request.response.setCookie(self.cookie_name, cookie, **kw)
  451. request.SESSION.set('__ac_username', username)
  452. request.response.setCookie('__ac_persistent', 'True', **kw)
  453. except (AttributeError, ValueError):
  454. pass
  455.  
  456. # IExtractionPlugin implementation
  457. security.declarePrivate('extractCredentials')
  458. def extractCredentials(self, request):
  459. """ Extract credentials from cookie or 'request'. """
  460. creds = {}
  461. cookie = request.get(self.cookie_name, '')
  462. # Look in the request.form for the names coming from the login form
  463. login = request.form.get('__ac_name', '')
  464.  
  465. if login and request.form.has_key('__ac_password'):
  466. creds['login'] = login
  467. password = request.form.get('__ac_password', '')
  468. creds['password'] = password
  469.  
  470. if request.get('password_hashed'):
  471. # this is for auto login -- auto login uses the hashed password
  472. creds['password'] = ''
  473. creds['passwordHash'] = password
  474.  
  475. elif cookie and cookie != 'deleted':
  476. creds.update(self._extract_from_cookie(request, cookie))
  477. if creds:
  478. creds['remote_host'] = request.get('REMOTE_HOST', '')
  479.  
  480. try:
  481. creds['remote_address'] = request.getClientAddr()
  482. except AttributeError:
  483. creds['remote_address'] = request.get('REMOTE_ADDR', '')
  484.  
  485. return creds
  486.  
  487. # IUserEnumerationPlugin implementation
  488. def enumerateUsers(self, id=None, login=None, exact_match=False,
  489. sort_by=None, max_results=None, **kw):
  490. login = id or login
  491. # we only find the logged in user because we can't enumerate erc users
  492. if self.REQUEST.SESSION.get('erc_id') == self.getId():
  493. member = self.portal_membership.getAuthenticatedMember()
  494. username = member.getUserName()
  495. if login == username:
  496. return ({
  497. 'id': id,
  498. 'login': login,
  499. 'pluginid': self.getId(),
  500. },)
  501.  
  502. # IUserManagement implementation
  503. def doChangeUser(self, login, password, **kw):
  504. """Change a user's password
  505.  
  506. We can only change the password of the current logged in user
  507. """
  508. member = self.portal_membership.getAuthenticatedMember()
  509. if self.REQUEST.SESSION.get('erc_id') == self.getId() and \
  510. login == member.getUserName():
  511. creds = self.extractCredentials(self.REQUEST)
  512. username = creds.get('username')
  513. old_password_hash = creds.get('passwordHash')
  514. if username and old_password_hash:
  515. self.changePassword(username, old_password_hash, password)
  516.  
  517. # IUserManagement implementation
  518. def doDeleteUser(login):
  519. return False
  520.  
  521. def registerNewUser(self, **kw):
  522. logging.getLogger('erc').debug('Se llama a register User en plugin.py')
  523. username = self.erc.registerNewUser(**kw)
  524. properties = {'username': username}
  525. properties.update(kw)
  526. zope.event.notify(events.ErcUserCreated(
  527. properties=properties, erc=self.erc))
  528. return username
  529.  
  530. def setCRMID(self, username, crmid, email=None):
  531. value = self.erc.setCRMID(username, crmid, email)
  532. if value.get('success'):
  533. zope.event.notify(events.ErcSetCrmid(properties={
  534. 'username': username,
  535. 'crmid': crmid,
  536. 'email': email,
  537. }, erc=self.erc))
  538. return simplejson.dumps(value)
  539.  
  540. def __getattr__(self, name):
  541. if not hasattr(self.erc, name):
  542. raise AttributeError
  543. return getattr(self.erc, name)
  544.  
  545. classImplements(ErcAuthPlugin,
  546. IAuthenticationPlugin,
  547. IRolesPlugin,
  548. IUserEnumerationPlugin,
  549. ICredentialsUpdatePlugin,
  550. ICredentialsResetPlugin,
  551. IExtractionPlugin,
  552. IUserEnumerationPlugin,
  553. IUserManagement,
  554. )
  555.  
  556. InitializeClass(ErcAuthPlugin)
  557.  
  558. manage_addErcMockPluginForm = PageTemplateFile(
  559. 'www/add_mock', globals(), __name__='manage_addErcMockPluginForm')
  560.  
  561. def manage_addErcMockPlugin(dispatcher, id, role_mapper_func,
  562. title=None, REQUEST=None):
  563. """Add a Erc mock plugin"""
  564. obj = ErcMockPlugin(id, title, role_mapper_func)
  565. dispatcher._setObject(obj.getId(), obj)
  566. obj = getattr(dispatcher, obj.getId())
  567. activate_all_interfaces(dispatcher, obj)
  568.  
  569. if REQUEST is not None:
  570. REQUEST['RESPONSE'].redirect(
  571. '%s/manage_workspace'
  572. '?manage_tabs_message='
  573. 'Erc+Mock+Plugin+added.'
  574. % dispatcher.absolute_url())
  575.  
  576. class ErcMockPlugin(ErcAuthPlugin):
  577. """ERC Mock Plugin"""
  578. meta_type = 'Erc Mock Plugin'
  579. security = ClassSecurityInfo()
  580.  
  581. manage_options = (
  582. {
  583. 'label': 'Name map',
  584. 'action': 'manage_configureErcNameMapForm',
  585. },
  586. {
  587. 'label': 'View users',
  588. 'action': 'manage_viewErcMockUsersForm',
  589. },
  590. ) + BasePlugin.manage_options
  591.  
  592. manage_viewErcMockUsersForm = PageTemplateFile(
  593. 'www/view_erc_mock_users', globals(),
  594. __name__='manage_viewErcMockUsersForm')
  595.  
  596. def __init__(self, id, title, role_mapper_func=None, erc_namemap=None):
  597. self._id = self.id = id
  598. self.title = title
  599. self.erc = ercmock.ErcMock(namemap=erc_namemap)
  600. if role_mapper_func:
  601. self.addRoleMapper(role_mapper_func)
  602. else:
  603. self.roleMapperFunc = 'drago.ercpas.plugin.role_mapper'
  604. self.erc_namemap = PersistentDict(self.erc.namemap)
  605. self.erc_users = PersistentDict(self.erc.users)
  606.  
  607. def registerNewUser(self, **kw):
  608. username = ErcAuthPlugin.registerNewUser(self, **kw)
  609. self.erc_users = PersistentDict(self.erc.users)
  610.  
  611. def __getattr__(self, name):
  612. if hasattr(ercmock.ErcMock, name):
  613. self.erc_users = PersistentDict(self.erc.users)
  614. return getattr(self.erc, name)
  615. return BasePlugin.__getattr__(self, name)
  616.  
  617. classImplements(ErcMockPlugin,
  618. IAuthenticationPlugin,
  619. IRolesPlugin,
  620. ICredentialsUpdatePlugin,
  621. ICredentialsResetPlugin,
  622. IExtractionPlugin,
  623. IUserEnumerationPlugin,
  624. IUserManagement,
  625. )
  626.  
  627. InitializeClass(ErcMockPlugin)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement