## ## authentication.py ## Login : ## Started on Tue Jul 27 14:26:35 2010 Uli Fouquet ## $Id$ ## ## Copyright (C) 2010 Uli Fouquet ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## """Special authentication for applicants. XXX: This is work in progress, experimental code! Don't do that at home! """ import grok from zope.event import notify from zope.pluggableauth.factories import Principal from zope.pluggableauth.interfaces import ( ICredentialsPlugin, IAuthenticatorPlugin, IPrincipalInfo, IAuthenticatedPrincipalFactory, AuthenticatedPrincipalCreated) from zope.pluggableauth.plugins.session import SessionCredentialsPlugin from zope.publisher.interfaces import IRequest from zope.publisher.interfaces.http import IHTTPRequest from zope.session.interfaces import ISession from waeup.sirp.authentication import Account, PrincipalInfo from waeup.sirp.jambtables.interfaces import ( IApplicantPrincipalInfo, IApplicantPrincipal) class PortalUser(grok.Role): """A role for applicants. """ grok.name('waeup.Applicant') grok.permissions('waeup.Public') class ApplicantAccount(Account): """An account for applicants. """ def __init__(self, reg_no, ac): self.name = u'applicant' self.title = u'Applicant' self.description = u'Applicant' self.reg_no = reg_no self.access_code = ac roles = ['waeup.Applicant'] self.setRoles(roles) def checkPassword(self, reg_no, ac): """Check whether the given credentials exist. `reg_no` is a JAMB registration number. `ac` an access code string like ``PUDE-23-1234567890``. """ if self.reg_no != reg_no or self.access_code != ac: return False return True site = grok.getSite() if not reg_no in site['applications']: return False data = get_applicant_data(reg_no, ac) if data is None: return False return True class ApplicantPrincipalInfo(object): grok.implements(IApplicantPrincipalInfo) # def __init__(self, id, title, description): def __init__(self, reg_no, access_code): self.id = '%s-%s' % (reg_no, access_code) self.title = u'Applicant' self.description = u'An Applicant' self.credentialsPlugin = None self.authenticatorPlugin = None self.reg_no = reg_no self.access_code = access_code class ApplicantPrincipal(Principal): grok.implements(IApplicantPrincipal) def __init__(self, reg_no, access_code): self.id = '%s-%s' % (reg_no, access_code) self.title = u'Applicant' self.description = u'An applicant' self.groups = [] self.reg_no = reg_no self.access_code = access_code def __repr__(self): return 'ApplicantPrincipal(%r)' % self.id class AuthenticatedApplicantPrincipalFactory(grok.MultiAdapter): """Creates 'authenticated' applicant principals. """ grok.adapts(IApplicantPrincipalInfo, IRequest) grok.implements(IAuthenticatedPrincipalFactory) def __init__(self, info, request): self.info = info self.request = request def __call__(self, authentication): principal = ApplicantPrincipal( authentication.prefix + self.info.reg_no, self.info.access_code ) notify( AuthenticatedPrincipalCreated( authentication, principal, self.info, self.request)) return principal class WAeUPApplicantCredentialsPlugin(grok.GlobalUtility, SessionCredentialsPlugin): grok.provides(ICredentialsPlugin) grok.name('applicant_credentials') loginpagename = 'login' loginfield = 'form.login' passwordfield = 'form.password' def extractCredentials(self, request): """Extracts credentials from a session if they exist. This is currently the implementation from zope.pluggableauth. XXX: Make this plugin handle login_pde-like input. """ if not IHTTPRequest.providedBy(request): return None session = ISession(request) sessionData = session.get( 'zope.pluggableauth.browserplugins') login = request.get(self.loginfield, None) password = request.get(self.passwordfield, None) credentials = None if login and password: credentials = SessionCredentials(login, password) elif not sessionData: return None sessionData = session[ 'zope.pluggableauth.browserplugins'] if credentials: sessionData['credentials'] = credentials else: credentials = sessionData.get('credentials', None) if not credentials: return None return {'login': credentials.getLogin(), 'password': credentials.getPassword()} class ApplicantsAuthenticatorPlugin(grok.GlobalUtility): """Authenticate applicants. XXX: This plugin currently accepts any input and authenticates the user as applicant. """ grok.provides(IAuthenticatorPlugin) grok.name('applicants') def authenticateCredentials(self, credentials): #print "AUTH: ", credentials if not isinstance(credentials, dict): return None if not 'login' in credentials.keys(): return None if not 'password' in credentials.keys(): return None return ApplicantPrincipalInfo( credentials['login'], credentials['password'] ) def principalInfo(self, id): """Returns an IPrincipalInfo object for the specified principal id. Currently we always return ``None``, indicating, that the principal could not be found. """ return None def principal_id(access_code, jamb_reg_no=None): """Get a principal ID for applicants. We need unique principal ids for appliants. As access codes must be unique we simply return them. """ return access_code