source: main/waeup.sirp/trunk/src/waeup/sirp/applicants/authentication.py @ 5879

Last change on this file since 5879 was 5818, checked in by uli, 14 years ago
  • Try to remove all JAMB related code
  • Remove unused imports
File size: 8.2 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,
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.accesscodes import get_access_code
37from waeup.sirp.applicants.interfaces import (
38    IApplicantPrincipalInfo, IApplicantPrincipal, IApplicantSessionCredentials,
39    IJAMBApplicantSessionCredentials)
40from waeup.sirp.applicants import get_applicant_data
41
42
43class PortalUser(grok.Role):
44    """A role for applicants.
45    """
46    grok.name('waeup.Applicant')
47    grok.permissions('waeup.Public')
48
49class ApplicantPrincipalInfo(object):
50    """Infos about an applicant principal.
51    """
52    grok.implements(IApplicantPrincipalInfo)
53
54    def __init__(self, access_code):
55        self.id = principal_id(access_code)
56        self.title = u'Applicant'
57        self.description = u'An Applicant'
58        self.credentialsPlugin = None
59        self.authenticatorPlugin = None
60        self.access_code = access_code
61
62class ApplicantPrincipal(Principal):
63    """An applicant principal.
64
65    Applicant principals provide an extra `access_code` and `reg_no`
66    attribute extending ordinary principals.
67    """
68
69    grok.implements(IApplicantPrincipal)
70
71    def __init__(self, access_code, prefix=None):
72        self.id = principal_id(access_code)
73        if prefix is not None:
74            self.id = '%s.%s' % (prefix, self.id)
75        self.title = u'Applicant'
76        self.description = u'An applicant'
77        self.groups = []
78        self.access_code = access_code
79
80    def __repr__(self):
81        return 'ApplicantPrincipal(%r)' % self.id
82
83class AuthenticatedApplicantPrincipalFactory(grok.MultiAdapter):
84    """Creates 'authenticated' applicant principals.
85
86    Adapts (principal info, request) to an ApplicantPrincipal instance.
87
88    This adapter is used by the standard PAU to transform
89    PrincipalInfos into Principal instances.
90    """
91    grok.adapts(IApplicantPrincipalInfo, IRequest)
92    grok.implements(IAuthenticatedPrincipalFactory)
93
94    def __init__(self, info, request):
95        self.info = info
96        self.request = request
97
98    def __call__(self, authentication):
99        principal = ApplicantPrincipal(
100            self.info.access_code,
101            authentication.prefix,
102            )
103        notify(
104            AuthenticatedPrincipalCreated(
105                authentication, principal, self.info, self.request))
106        return principal
107
108
109#
110# Credentials plugins and related....
111#
112
113class ApplicantCredentials(object):
114    """Credentials class for ordinary applicants.
115    """
116    grok.implements(IApplicantSessionCredentials)
117
118    def __init__(self, access_code):
119        self.access_code = access_code
120
121    def getAccessCode(self):
122        """Get the access code.
123        """
124        return self.access_code
125
126    def getLogin(self):
127        """Stay compatible with non-applicant authenticators.
128        """
129        return None
130
131    def getPassword(self):
132        """Stay compatible with non-applicant authenticators.
133        """
134        return None
135   
136class JAMBApplicantCredentials(ApplicantCredentials):
137    """Credentials class for JAMB-screened applicants.
138    """
139    grok.implements(IJAMBApplicantSessionCredentials)
140
141    def __init__(self, access_code):
142        self.access_code = access_code
143
144class WAeUPApplicantCredentialsPlugin(grok.GlobalUtility,
145                                      SessionCredentialsPlugin):
146    """A credentials plugin that scans requests for applicant credentials.
147    """
148    grok.provides(ICredentialsPlugin)
149    grok.name('applicant_credentials')
150
151    loginpagename = 'login'
152    accesscode_prefix_field = 'form.prefix'
153    accesscode_series_field = 'form.ac_series'
154    accesscode_number_field = 'form.ac_number'
155
156    def extractCredentials(self, request):
157        """Extracts credentials from a session if they exist.
158        """
159        if not IHTTPRequest.providedBy(request):
160            return None
161        session = ISession(request)
162        sessionData = session.get(
163            'zope.pluggableauth.browserplugins')
164        access_code_prefix = request.get(self.accesscode_prefix_field, None)
165        access_code_series = request.get(self.accesscode_series_field, None)
166        access_code_no = request.get(self.accesscode_number_field, None)
167        access_code = '%s-%s-%s' % (
168            access_code_prefix, access_code_series, access_code_no)
169        if None in [access_code_prefix, access_code_series, access_code_no]:
170            access_code = None
171        credentials = None
172
173        if access_code:
174            credentials = ApplicantCredentials(access_code)
175        elif not sessionData:
176            return None
177        sessionData = session[
178            'zope.pluggableauth.browserplugins']
179        if credentials:
180            sessionData['credentials'] = credentials
181        else:
182            credentials = sessionData.get('credentials', None)
183        if not credentials:
184            return None
185        if not IApplicantSessionCredentials.providedBy(credentials):
186            # If credentials were stored in session from another
187            # credentials plugin then we cannot make assumptions about
188            # its structure.
189            return None
190
191        # Entered credentials are ordinary applicant credentials,
192        # not JAMB-screened applicant credentials
193        return {'accesscode': credentials.getAccessCode()}
194
195
196
197class ApplicantsAuthenticatorPlugin(grok.GlobalUtility):
198    """Authenticate applicants.
199
200    XXX: This plugin currently accepts any input and authenticates the
201    user as applicant.
202    """
203    grok.provides(IAuthenticatorPlugin)
204    grok.name('applicants')
205
206    def authenticateCredentials(self, credentials):
207        if not isinstance(credentials, dict):
208            return None
209        accesscode = credentials.get('accesscode', None)
210        if accesscode is None:
211            return None
212        applicant_data = get_applicant_data(accesscode)
213        ac = get_access_code(accesscode) # Get the real access code object
214        appl_ac = getattr(applicant_data, 'access_code', None)
215        if ac is None:
216            return None
217        if ac.invalidation_date is not None and appl_ac != ac.representation:
218            return None
219        if appl_ac is not None and appl_ac != ac.representation:
220            return None
221        return ApplicantPrincipalInfo(accesscode)
222
223    def principalInfo(self, id):
224        """Returns an IPrincipalInfo object for the specified principal id.
225
226        This method is used by the stadard PAU to lookup for instance
227        groups. If a principal belongs to a group, the group is looked
228        up by the id.  Currently we always return ``None``,
229        indicating, that the principal could not be found. This also
230        means, that is has no effect if applicant users belong to a
231        certain group. They can not gain extra-permissions this way.
232        """
233        return None
234
235def principal_id(access_code):
236    """Get a principal ID for applicants.
237
238    We need unique principal ids for appliants. As access codes must
239    be unique we simply return them.
240    """
241    return access_code
Note: See TracBrowser for help on using the repository browser.