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

Last change on this file since 5442 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
Line 
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 (
38    IApplicantPrincipalInfo, IApplicantPrincipal, IApplicantSessionCredentials,
39    IJAMBApplicantSessionCredentials)
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.
49
50    XXX: Very likely we do not need this at all.
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):
79    """Infos about an applicant principal.
80    """
81    grok.implements(IApplicantPrincipalInfo)
82
83    # def __init__(self, id, title, description):
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)
87        self.title = u'Applicant'
88        self.description = u'An Applicant'
89        self.credentialsPlugin = None
90        self.authenticatorPlugin = None
91        self.reg_no = jamb_reg_no
92        self.access_code = access_code
93
94class ApplicantPrincipal(Principal):
95    """An applicant principal.
96
97    Applicant principals provide an extra `access_code` and `reg_no`
98    attribute extending ordinary principals.
99    """
100
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.
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.
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
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
171class WAeUPApplicantCredentialsPlugin(grok.GlobalUtility,
172                                      SessionCredentialsPlugin):
173    """A credentials plugin that scans requests for applicant credentials.
174    """
175    grok.provides(ICredentialsPlugin)
176    grok.name('applicant_credentials')
177
178    loginpagename = 'login'
179    accesscode_field = 'form.access_code'
180    jamb_reg_no_field = 'form.jamb_reg_no'
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')
190        access_code = request.get(self.accesscode_field, None)
191        jamb_reg_no = request.get(self.jamb_reg_no_field, None)
192        credentials = None
193
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)
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
209        if credentials.getJAMBRegNo() is not None:
210            return {'accesscode': credentials.getAccessCode(),
211                    'jambregno': credentials.getJAMBRegNo()}
212        return {'accesscode': credentials.getAccessCode()}
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
228        if not 'accesscode' in credentials.keys():
229            return None
230        if not 'jambregno' in credentials.keys():
231            credentials['jambregno'] = None
232        return ApplicantPrincipalInfo(
233            credentials['accesscode'], credentials['jambregno']
234            # credentials['login'], credentials['password']
235            )
236
237    def principalInfo(self, id):
238        """Returns an IPrincipalInfo object for the specified principal id.
239
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.
246        """
247        return None
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.