source: main/waeup.sirp/trunk/src/waeup/sirp/jambtables/authentication.py @ 5443

Last change on this file since 5443 was 5441, checked in by uli, 14 years ago
  • Be more verbose in docstrings.
  • Consider correct field names when authenticating (don't ask for 'login' and 'password' field anymore.
File size: 8.5 KB
RevLine 
[5431]1##
2## authentication.py
3## Login : <uli@pu.smp.net>
4## Started on  Tue Jul 27 14:26:35 2010 Uli Fouquet
5## $Id$
6##
7## Copyright (C) 2010 Uli Fouquet
8## This program is free software; you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation; either version 2 of the License, or
11## (at your option) any later version.
12##
13## This program is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with this program; if not, write to the Free Software
20## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21##
22"""Special authentication for applicants.
23
24   XXX: This is work in progress, experimental code! Don't do that at home!
25"""
26import grok
27from zope.event import notify
28from zope.pluggableauth.factories import Principal
29from zope.pluggableauth.interfaces import (
30    ICredentialsPlugin, IAuthenticatorPlugin, IPrincipalInfo,
31    IAuthenticatedPrincipalFactory, AuthenticatedPrincipalCreated)
32from zope.pluggableauth.plugins.session import SessionCredentialsPlugin
33from zope.publisher.interfaces import IRequest
34from zope.publisher.interfaces.http import IHTTPRequest
35from zope.session.interfaces import ISession
36from waeup.sirp.authentication import Account, PrincipalInfo
37from waeup.sirp.jambtables.interfaces import (
[5440]38    IApplicantPrincipalInfo, IApplicantPrincipal, IApplicantSessionCredentials,
39    IJAMBApplicantSessionCredentials)
[5431]40
41class PortalUser(grok.Role):
42    """A role for applicants.
43    """
44    grok.name('waeup.Applicant')
45    grok.permissions('waeup.Public')
46
47class ApplicantAccount(Account):
48    """An account for applicants.
[5441]49
50    XXX: Very likely we do not need this at all.
[5431]51    """
52    def __init__(self, reg_no, ac):
53        self.name = u'applicant'
54        self.title = u'Applicant'
55        self.description = u'Applicant'
56        self.reg_no = reg_no
57        self.access_code = ac
58        roles = ['waeup.Applicant']
59        self.setRoles(roles)
60
61    def checkPassword(self, reg_no, ac):
62        """Check whether the given credentials exist.
63
64        `reg_no` is a JAMB registration number. `ac` an access code
65        string like ``PUDE-23-1234567890``.
66        """
67        if self.reg_no != reg_no or self.access_code != ac:
68            return False
69        return True
70        site = grok.getSite()
71        if not reg_no in site['applications']:
72            return False
73        data = get_applicant_data(reg_no, ac)
74        if data is None:
75            return False
76        return True
77
78class ApplicantPrincipalInfo(object):
[5441]79    """Infos about an applicant principal.
80    """
[5431]81    grok.implements(IApplicantPrincipalInfo)
82
83    # def __init__(self, id, title, description):
[5441]84    # def __init__(self, reg_no, access_code):
85    def __init__(self, access_code, jamb_reg_no=None):
86        self.id = princial_id(access_code, jamb_reg_no)
[5431]87        self.title = u'Applicant'
88        self.description = u'An Applicant'
89        self.credentialsPlugin = None
90        self.authenticatorPlugin = None
[5441]91        self.reg_no = jamb_reg_no
[5431]92        self.access_code = access_code
93
94class ApplicantPrincipal(Principal):
[5441]95    """An applicant principal.
[5431]96
[5441]97    Applicant principals provide an extra `access_code` and `reg_no`
98    attribute extending ordinary principals.
99    """
100
[5431]101    grok.implements(IApplicantPrincipal)
102
103    def __init__(self, reg_no, access_code):
104        self.id = '%s-%s' % (reg_no, access_code)
105        self.title = u'Applicant'
106        self.description = u'An applicant'
107        self.groups = []
108        self.reg_no = reg_no
109        self.access_code = access_code
110
111    def __repr__(self):
112        return 'ApplicantPrincipal(%r)' % self.id
113
114class AuthenticatedApplicantPrincipalFactory(grok.MultiAdapter):
115    """Creates 'authenticated' applicant principals.
[5441]116
117    Adapts (principal info, request) to an ApplicantPrincipal instance.
118
119    This adapter is used by the standard PAU to transform
120    PrincipalInfos into Principal instances.
[5431]121    """
122    grok.adapts(IApplicantPrincipalInfo, IRequest)
123    grok.implements(IAuthenticatedPrincipalFactory)
124
125    def __init__(self, info, request):
126        self.info = info
127        self.request = request
128
129    def __call__(self, authentication):
130        principal = ApplicantPrincipal(
131            authentication.prefix + self.info.reg_no,
132            self.info.access_code
133            )
134        notify(
135            AuthenticatedPrincipalCreated(
136                authentication, principal, self.info, self.request))
137        return principal
138
[5440]139
140#
141# Credentials plugins and related....
142#
143
144class ApplicantCredentials(object):
145    """Credentials class for ordinary applicants.
146    """
147    grok.implements(IApplicantSessionCredentials)
148
149    def __init__(self, access_code):
150        self.access_code = access_code
151
152    def getAccessCode(self):
153        """Get the access code.
154        """
155        return self.access_code
156
157class JAMBApplicantCredentials(ApplicantCredentials):
158    """Credentials class for JAMB-screened applicants.
159    """
160    grok.implements(IJAMBApplicantSessionCredentials)
161
162    def __init__(self, access_code, jamb_reg_no):
163        self.access_code = access_code
164        self.jamb_reg_no = jamb_reg_no
165
166    def getJAMBRegNo(self):
167        """Get the JAMB registration no.
168        """
169        return self.jamb_reg_no
170
[5431]171class WAeUPApplicantCredentialsPlugin(grok.GlobalUtility,
172                                      SessionCredentialsPlugin):
[5440]173    """A credentials plugin that scans requests for applicant credentials.
174    """
[5431]175    grok.provides(ICredentialsPlugin)
176    grok.name('applicant_credentials')
177
178    loginpagename = 'login'
[5440]179    accesscode_field = 'form.access_code'
180    jamb_reg_no_field = 'form.jamb_reg_no'
[5431]181
182    def extractCredentials(self, request):
183        """Extracts credentials from a session if they exist.
184        """
185        if not IHTTPRequest.providedBy(request):
186            return None
187        session = ISession(request)
188        sessionData = session.get(
189            'zope.pluggableauth.browserplugins')
[5441]190        access_code = request.get(self.accesscode_field, None)
[5440]191        jamb_reg_no = request.get(self.jamb_reg_no_field, None)
[5431]192        credentials = None
193
[5440]194        if access_code and jamb_reg_no:
195            credentials = JAMBApplicantCredentials(
196                access_code, jamb_reg_no)
197        elif access_code:
198            credentials = ApplicantCredentials(access_code)
[5431]199        elif not sessionData:
200            return None
201        sessionData = session[
202            'zope.pluggableauth.browserplugins']
203        if credentials:
204            sessionData['credentials'] = credentials
205        else:
206            credentials = sessionData.get('credentials', None)
207        if not credentials:
208            return None
[5440]209        if credentials.getJAMBRegNo() is not None:
210            return {'accesscode': credentials.getAccessCode(),
211                    'jambregno': credentials.getJAMBRegNo()}
212        return {'accesscode': credentials.getAccessCode()}
[5431]213
214
215class ApplicantsAuthenticatorPlugin(grok.GlobalUtility):
216    """Authenticate applicants.
217
218    XXX: This plugin currently accepts any input and authenticates the
219    user as applicant.
220    """
221    grok.provides(IAuthenticatorPlugin)
222    grok.name('applicants')
223
224    def authenticateCredentials(self, credentials):
225        #print "AUTH: ", credentials
226        if not isinstance(credentials, dict):
227            return None
[5441]228        if not 'accesscode' in credentials.keys():
[5431]229            return None
[5441]230        if not 'jambregno' in credentials.keys():
231            credentials['jambregno'] = None
[5431]232        return ApplicantPrincipalInfo(
[5441]233            credentials['accesscode'], credentials['jambregno']
234            # credentials['login'], credentials['password']
[5431]235            )
236
237    def principalInfo(self, id):
238        """Returns an IPrincipalInfo object for the specified principal id.
239
[5441]240        This method is used by the stadard PAU to lookup for instance
241        groups. If a principal belongs to a group, the group is looked
242        up by the id.  Currently we always return ``None``,
243        indicating, that the principal could not be found. This also
244        means, that is has no effect if applicant users belong to a
245        certain group. They can not gain extra-permissions this way.
[5431]246        """
247        return None
[5435]248
249def principal_id(access_code, jamb_reg_no=None):
250    """Get a principal ID for applicants.
251
252    We need unique principal ids for appliants. As access codes must
253    be unique we simply return them.
254    """
255    return access_code
Note: See TracBrowser for help on using the repository browser.