"""Authentication for WAeUP portals. """ import grok from zope import schema from zope.app.authentication.session import SessionCredentialsPlugin from zope.app.authentication.interfaces import (ICredentialsPlugin, IAuthenticatorPlugin, IPrincipalInfo, IPasswordManager) from zope.app.security.interfaces import (IAuthentication, IUnauthenticatedPrincipal, ILogout) from zope.component import getUtility from zope.interface import Interface from waeup.interfaces import IWAeUPObject, IUserAccount from waeup.viewlets import Index, MainArea, LeftSidebar import waeup.permissions def setup_authentication(pau): """Set up plugguble authentication utility. Sets up an IAuthenticatorPlugin and ICredentialsPlugin (for the authentication mechanism) """ pau.credentialsPlugins = ['credentials'] pau.authenticatorPlugins = ['users'] class WAeUPSessionCredentialsPlugin(grok.GlobalUtility, SessionCredentialsPlugin): grok.provides(ICredentialsPlugin) grok.name('credentials') loginpagename = 'login' loginfield = 'form.login' passwordfield = 'form.password' class Login(grok.View): grok.context(IWAeUPObject) # grok.require('zope.Public') # XXX: Does not work in ftests! def update(self, SUBMIT=None): self.camefrom = self.request.form.get('camefrom', '') if SUBMIT is not None: self.redirect(self.camefrom) class LoginMain(grok.Viewlet): grok.viewletmanager(MainArea) grok.context(IWAeUPObject) grok.view(Login) class Logout(grok.Viewlet): grok.viewletmanager(LeftSidebar) grok.context(IWAeUPObject) grok.order(3) # grok.require('zope.Public') # XXX: Does not work in ftests! def update(self): if 'form.logout' not in self.request.form.keys(): return if not IUnauthenticatedPrincipal.providedBy(self.request.principal): auth = getUtility(IAuthentication) ILogout(auth).logout(self.request) # We redirect to ourself, as we want this page be loaded # without authentication (updating other viewlets on the # page) self.view.redirect(self.view.url()) class PrincipalInfo(object): grok.implements(IPrincipalInfo) def __init__(self, id, title, description): self.id = id self.title = title self.description = description self.credentialsPlugin = None self.authenticatorPlugin = None class Account(grok.Model): grok.implements(IUserAccount) def __init__(self, name, password, title=None, description=None): self.name = name if title is None: title = name if description is None: description = title self.title = title self.description = description self.setPassword(password) def setPassword(self, password): passwordmanager = getUtility(IPasswordManager, 'SHA1') self.password = passwordmanager.encodePassword(password) def checkPassword(self, password): passwordmanager = getUtility(IPasswordManager, 'SHA1') return passwordmanager.checkPassword(self.password, password) class UserAuthenticatorPlugin(grok.GlobalUtility): grok.provides(IAuthenticatorPlugin) grok.name('users') def authenticateCredentials(self, credentials): if not isinstance(credentials, dict): return None if not ('login' in credentials and 'password' in credentials): return None account = self.getAccount(credentials['login']) if account is None: return None if not account.checkPassword(credentials['password']): return None return PrincipalInfo(id=account.name, title=account.name, description=account.name) def principalInfo(self, id): account = self.getAccount(id) if account is None: return None return PrincipalInfo(id=account.name, title=account.name, description=account.name) def getAccount(self, login): # XXX: while developing, we only support a single user. if login == 'grok': return Account('grok', 'grok') # ... look up the account object and return it ... usercontainer = self.getUserContainer() if usercontainer is None: return return usercontainer.get(login, None) def addAccount(self, account): usercontainer = self.getUserContainer() if usercontainer is None: return # XXX: complain if name already exists... usercontainer.addAccount(account) def addUser(self, name, password, title=None, description=None): usercontainer = self.getUserContainer() if usercontainer is None: return usercontainer.addUser(name, password, title, description) def getUserContainer(self): site = grok.getSite() return getattr(site, 'users', None)