source: waeup/branches/ulif-rewrite/src/waeup/authentication.py @ 4109

Last change on this file since 4109 was 4109, checked in by uli, 15 years ago

Let Account implement IUserAccount.

File size: 5.2 KB
Line 
1"""Authentication for WAeUP portals.
2"""
3import grok
4from zope import schema
5from zope.app.authentication.session import SessionCredentialsPlugin
6from zope.app.authentication.interfaces import (ICredentialsPlugin,
7                                                IAuthenticatorPlugin,
8                                                IPrincipalInfo,
9                                                IPasswordManager)
10from zope.app.security.interfaces import (IAuthentication,
11                                          IUnauthenticatedPrincipal,
12                                          ILogout)
13from zope.component import getUtility
14from zope.interface import Interface
15from waeup.interfaces import IWAeUPObject, IUserAccount
16from waeup.viewlets import Index, MainArea, LeftSidebar
17import waeup.permissions
18
19def setup_authentication(pau):
20    """Set up plugguble authentication utility.
21
22    Sets up an IAuthenticatorPlugin and
23    ICredentialsPlugin (for the authentication mechanism)
24    """
25    pau.credentialsPlugins = ['credentials']
26    pau.authenticatorPlugins = ['users']
27
28class WAeUPSessionCredentialsPlugin(grok.GlobalUtility,
29                                    SessionCredentialsPlugin):
30    grok.provides(ICredentialsPlugin)
31    grok.name('credentials')
32
33    loginpagename = 'login'
34    loginfield = 'form.login'
35    passwordfield = 'form.password'
36
37class Login(grok.View):
38    grok.context(IWAeUPObject)
39    # grok.require('zope.Public') # XXX: Does not work in ftests!
40
41    def update(self, SUBMIT=None):
42        self.camefrom = self.request.form.get('camefrom', '')
43        if SUBMIT is not None:
44            self.redirect(self.camefrom)
45           
46class LoginMain(grok.Viewlet):
47    grok.viewletmanager(MainArea)
48    grok.context(IWAeUPObject)
49    grok.view(Login)
50
51class Logout(grok.Viewlet):
52    grok.viewletmanager(LeftSidebar)
53    grok.context(IWAeUPObject)
54    grok.order(3)
55    # grok.require('zope.Public') # XXX: Does not work in ftests!
56   
57    def update(self):
58        if 'form.logout' not in self.request.form.keys():
59            return
60        if not IUnauthenticatedPrincipal.providedBy(self.request.principal):
61            auth = getUtility(IAuthentication)
62            ILogout(auth).logout(self.request)
63            # We redirect to ourself, as we want this page be loaded
64            # without authentication (updating other viewlets on the
65            # page)
66            self.view.redirect(self.view.url())
67
68class PrincipalInfo(object):
69    grok.implements(IPrincipalInfo)
70
71    def __init__(self, id, title, description):
72        self.id = id
73        self.title = title
74        self.description = description
75        self.credentialsPlugin = None
76        self.authenticatorPlugin = None
77
78class Account(grok.Model):
79    grok.implements(IUserAccount)
80   
81    def __init__(self, name, password, title=None, description=None):
82        self.name = name
83        if title is None:
84            title = name
85        if description is None:
86            description = title
87        self.title = title
88        self.description = description
89        self.setPassword(password)
90
91    def setPassword(self, password):
92        passwordmanager = getUtility(IPasswordManager, 'SHA1')
93        self.password = passwordmanager.encodePassword(password)
94
95    def checkPassword(self, password):
96        passwordmanager = getUtility(IPasswordManager, 'SHA1')
97        return passwordmanager.checkPassword(self.password, password)
98
99 
100class UserAuthenticatorPlugin(grok.GlobalUtility):
101    grok.provides(IAuthenticatorPlugin)
102    grok.name('users')
103
104    def authenticateCredentials(self, credentials):
105        if not isinstance(credentials, dict):
106            return None
107        if not ('login' in credentials and 'password' in credentials):
108            return None
109        account = self.getAccount(credentials['login'])
110
111        if account is None:
112            return None
113        if not account.checkPassword(credentials['password']):
114            return None
115        return PrincipalInfo(id=account.name,
116                             title=account.name,
117                             description=account.name)
118
119    def principalInfo(self, id):
120        account = self.getAccount(id)
121        if account is None:
122            return None
123        return PrincipalInfo(id=account.name,
124                             title=account.name,
125                             description=account.name)
126
127    def getAccount(self, login):
128        # XXX: while developing, we only support a single user.
129        if login == 'grok':
130            return Account('grok', 'grok')
131
132        # ... look up the account object and return it ...
133        usercontainer = self.getUserContainer()
134        if usercontainer is None:
135            return
136        return usercontainer.get(login, None)
137
138    def addAccount(self, account):
139        usercontainer = self.getUserContainer()
140        if usercontainer is None:
141            return
142        # XXX: complain if name already exists...
143        usercontainer.addAccount(account)
144
145    def addUser(self, name, password, title=None, description=None):
146        usercontainer = self.getUserContainer()
147        if usercontainer is None:
148            return
149        usercontainer.addUser(name, password, title, description)
150       
151    def getUserContainer(self):
152        site = grok.getSite()
153        return getattr(site, 'users', None)
Note: See TracBrowser for help on using the repository browser.