[Grok-dev] Make self.request.principal to be an instance of MyOwnPrincipalInfo (my own class)
Hector Blanco
white.lists at gmail.com
Wed Jan 12 13:12:25 EST 2011
Thank you for your reply, J.W.
I tried your latest solution... with same results... Maybe I have to
register the "MyOwnPrincipalInfo" somewhere else...
I can always get workarounds so is not too vital... is just that it'd
be nice to get it working (mostly to understand a little bit better
how all that works... out of curiosity...)
Just in case, let me detail the tools involved in the authentication
(maybe it's just a little silly detail with a pretty straight-forward
solution).
In app.py I have:
# = = = = = app.py = = = = = = = = = = = = = = = = = = = = #
from backlib.user import MyOwnPrincipalInfo # <-- This is what I want :-)
from backlib.database import Database
import grok
# ... other imports...
from zope.authentication.interfaces import IAuthentication
from zope.authentication.interfaces import ILogout
from zope.authentication.interfaces import IUnauthenticatedPrincipal
from zope.interface import Interface
from zope.pluggableauth.authentication import PluggableAuthentication
from zope.pluggableauth.interfaces import IAuthenticatorPlugin
from zope.pluggableauth.interfaces import ICredentialsPlugin
from zope.pluggableauth.plugins.session import SessionCredentialsPlugin
from zope.security import checkPermission
def setup_authentication(pau):
pau.credentialsPlugins = ['credentials']
pau.authenticatorPlugins = ['myAuthenticatorPlugin']
class Server(grok.Application, grok.Container):
grok.local_utility(
PluggableAuthentication, provides=IAuthentication,
setup=setup_authentication,
)
def __init__(self):
super(Server, self).__init__()
# ... yadda ... yadda ...
# End of class Server
class MySessionCredentialsPlugin(grok.GlobalUtility, SessionCredentialsPlugin):
grok.provides(ICredentialsPlugin)
grok.name('credentials')
loginpagename = 'login'
loginfield = 'form.login'
passwordfield = 'form.hashedPwd'
# End of class MySessionCredentialsPlugin
class UserAuthenticatorPlugin(grok.GlobalUtility):
grok.provides(IAuthenticatorPlugin)
grok.name('myAuthenticatorPlugin')
grok.context(Server)
def authenticateCredentials(self, credentials):
if isinstance(credentials, dict):
if (("login" in credentials) and ("password" in credentials)):
user = self.getAccount(credentials['login'])
if user and (user.checkPassword(credentials['password'])):
return MyOwnPrincipalInfo.MyOwnPrincipalInfo(user)
return None
def principalInfo(self, principalName):
# May the answer be here ??
return self.getAccount(principalName)
def getAccount(self, login):
if not(login.startswith("zope.") or login == "zope.manager"):
try:
return grok.getSite()["UserManager"].getByName(login)
except Exception, e:
log.warn("::UserAuthenticatorPlugin > getAccount > Got exception %s " % e)
finally:
Database.session.close()
else:
return None
# End of class UserAuthenticatorPlugin
class ILoginForm(Interface):
login = schema.TextLine(title=u'Username', required=True)
hashedPwd = schema.BytesLine(title=u'HashedPwd', required=True)
class Login(grok.Form):
grok.context(Interface)
grok.require('zope.Public')
form_fields = grok.Fields(ILoginForm)
@grok.action('login')
def handle_login(self, ** data):
if self.request.form.get('camefrom', ''):
redirect = (self.request.form.get('camefrom', '')).split('/')[-1]
self.redirect(self.url(redirect))
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
And the the MyOwnPrincipalInfo is in another .py file (in the
"backlib/user/" folder):
# = = = = = MyOwnPrincipalInfo.py = = = = = = = = = = = = = = = = #
from backlib.user import User
import grok
# ... other imports...
from zope.pluggableauth.interfaces import IPrincipalInfo
from zope.publisher.interfaces.browser import IBrowserRequest
class MyOwnPrincipalInfo(grok.MultiAdapter):
grok.adapts(IPrincipalInfo, IBrowserRequest)
grok.implements(IPrincipalInfo)
def __init__(self, user):
super(MyOwnPrincipalInfo, self).__init__()
if isinstance(user, User.User) and (user.id):
self.id = str(user.id)
self.title = user.userName
self.description = str(user.firstName) + " " + str(user.lastName)
else:
raise TypeError("Unable to provide a PrincipalInfo from a %s" % type(user))
#End __init__
def someOtherVeryCoolStuff(self):
# do whatever
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
But still... if in a view (which are defined in app.py, by the way...
JIC) I try to access:
self.request.principal.someOtherVeryCoolStuff()
(for instance:
class Test(grok.View):
grok.context(Server)
grok.require('server.ViewSite')
def update(self):
print "Type of the principal: %s\n" % type(self.request.principal)
print "self.request.principal.someOtherVeryCoolStuff(): %s" %
self.request.principal.someOtherVeryCoolStuff()
)
I get the same exception:
Type of the principal: <class 'zope.pluggableauth.factories.Principal'>
2011-01-12 13:08:08,295 ERROR [SiteError] http://127.0.0.1:8080/myOwn-cms/test
Traceback (most recent call last):
File "/home/ae/.buildout/eggs/zope.publisher-3.12.4-py2.6.egg/zope/publisher/publish.py",
line 132, in publish
result = publication.callObject(request, obj)
File "/home/ae/.buildout/eggs/grok-1.2.1-py2.6.egg/grok/publication.py",
line 90, in callObject
return super(ZopePublicationSansProxy, self).callObject(request, ob)
File "/home/ae/.buildout/eggs/zope.app.publication-3.12.0-py2.6.egg/zope/app/publication/zopepublication.py",
line 207, in callObject
return mapply(ob, request.getPositionalArguments(), request)
File "/home/ae/.buildout/eggs/zope.publisher-3.12.4-py2.6.egg/zope/publisher/publish.py",
line 107, in mapply
return debug_call(obj, args)
File "/home/ae/.buildout/eggs/zope.publisher-3.12.4-py2.6.egg/zope/publisher/publish.py",
line 113, in debug_call
return obj(*args)
File "/home/ae/.buildout/eggs/grokcore.view-1.13.5-py2.6.egg/grokcore/view/components.py",
line 92, in __call__
mapply(self.update, (), self.request)
File "/home/ae/.buildout/eggs/zope.publisher-3.12.4-py2.6.egg/zope/publisher/publish.py",
line 107, in mapply
return debug_call(obj, args)
File "/home/ae/.buildout/eggs/zope.publisher-3.12.4-py2.6.egg/zope/publisher/publish.py",
line 113, in debug_call
return obj(*args)
File "/home/ae/myOwn-cms/server/src/server/app.py", line 180, in update
print "self.request.principal.someOtherVeryCoolStuff(): %s" %
self.request.principal.someOtherVeryCoolStuff()
AttributeError: 'Principal' object has no attribute 'someOtherVeryCoolStuff'
As I said, I can get some workarounds, but it'd be nice to get it
working so I could understand a bit better the authentication system.
Thank you!
2011/1/10 Hector Blanco <white.lists at gmail.com>:
> Hello!
>
> Thanks for all your replies
>
> 2011/1/10 Jan-Wijbrand Kolman <janwijbrand at gmail.com>:
>> On 1/9/11 21:57 PM, Hector Blanco wrote:
>>> --------------- (in app.py) ---------------
>>> def authenticateCredentials(self, credentials):
>>> if isinstance(credentials, dict):
>>> if (("login" in credentials) and ("password" in credentials)):
>>> user = self.getAccount(credentials['login'])
>>> if user and (user.checkPassword(credentials['password'])):
>>> return MyOwnPrincipalInfo.MyOwnPrincipalInfo(user)
>>> return None
>
>>
>> This "def authenticateCredentials()" method is implemented where in your
>> code? If you want to do this, you'd need to create your own
>> IAuthentication utility and register that for you site.
>>
>
> I put it in app.py
>
>> Another possibility, if you for some reason you cannot use the dolmen.*
>> packages that would provide features you are looking for, is to create
>> your own IAuthenticatedPrincipalFactory adapter.
>>
>> This adapter is looked up whenever the Pluggable Authentication Utility
>> creates an authenticated principal from the principal info that was
>> found. There you could hook in you own implementation, something like
>> (incomplete and untested, but I hope you get the idea!):
>>
>> class MyOwnPrincipalInfo(grok.MultiAdapter):
>> grok.adapts(IPrincipalInfo, IBrowserRequest)
>> grok.implements(IPrincipalInfo)
>>
>> def someOtherVeryCoolStuff(self):
>> # do whatever
>>
>> HTH
>>
>
> Gonna try that... Let's see what happens :)
>
>> regrrds, jw
>>
>
> Thanks again for all the hints
>
More information about the Grok-dev
mailing list