[Grok-dev] Make self.request.principal to be an instance of MyOwnPrincipalInfo (my own class)

Hector Blanco white.lists at gmail.com
Sun Jan 23 19:00:34 EST 2011


I have been doing some more testings, but with luck...

If I try (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 component.getMultiAdapter((user), IPrincipalInfo)
I get a:
  File "/home/hbr/.buildout/eggs/zope.pluggableauth-1.2-py2.6.egg/zope/pluggableauth/authentication.py",
line 63, in authenticate
    info = authplugin.authenticateCredentials(credentials)
  File "/home/hbr/Documents/myown-cms/server/src/server/app.py", line
91, in authenticateCredentials
    return component.getMultiAdapter((user), IPrincipalInfo)
  File "/home/hbr/.buildout/eggs/zope.component-3.10.0-py2.6.egg/zope/component/_api.py",
line 108, in getMultiAdapter
    adapter = queryMultiAdapter(objects, interface, name, context=context)
  File "/home/hbr/.buildout/eggs/zope.component-3.10.0-py2.6.egg/zope/component/_api.py",
line 121, in queryMultiAdapter
    return sitemanager.queryMultiAdapter(objects, interface, name, default)
  File "/home/hbr/.buildout/eggs/zope.component-3.10.0-py2.6.egg/zope/component/registry.py",
line 238, in queryMultiAdapter
    return self.adapters.queryMultiAdapter(objects, interface, name, default)
  File "/home/hbr/.buildout/eggs/zope.interface-3.6.1-py2.6-linux-x86_64.egg/zope/interface/adapter.py",
line 528, in queryMultiAdapter
    factory = self.lookup(map(providedBy, objects), provided, name)

Or with some other tries, I get a "Could not adapt" exception...

I'm a bit lost, here...

I was reading about the Dolmen/Menhir packages, but it seems to me
that it might be a little bit too much for my needs. It seems I'm
getting closer, but still, not enough...

Any hint will be appreciated! Thank you!


2011/1/12 Hector Blanco <white.lists at gmail.com>:
> 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