tgrepozewho

3 views
Skip to first unread message

percious

unread,
May 7, 2008, 4:12:57 PM5/7/08
to TurboGears Trunk
I tried putting tgrepozewho up on our linux server and it failed
wonderfully. Something about userid being a long that it doesnt
like. Where is the right place to cast the userid into a string?

cheers.
-chris

URL: http://sccdata:13001/login_handler?came_from=http://sccdata:13001/
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
WebError-0.8a-py2.5.egg/weberror/evalexception/middleware.py', line
364 in respond
app_iter = self.application(environ, detect_start_response)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
ToscaWidgets-0.8.5-py2.5.egg/tw/core/middleware.py', line 39 in
__call__
return self.wsgi_app(environ, start_response)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
Paste-1.6-py2.5.egg/paste/registry.py', line 334 in __call__
app_iter = self.application(environ, start_response)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
ToscaWidgets-0.8.5-py2.5.egg/tw/core/middleware.py', line 54 in
wsgi_app
app_iter = self.application(environ, start_response)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
Beaker-0.9.4-py2.5.egg/beaker/middleware.py', line 75 in __call__
return self.app(environ, start_response)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
Beaker-0.9.4-py2.5.egg/beaker/middleware.py', line 147 in __call__
return self.wrap_app(environ, session_start_response)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
Routes-1.8-py2.5.egg/routes/middleware.py', line 99 in __call__
response = self.app(environ, start_response)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
repoze.who-0.9.1-py2.5.egg/repoze/who/middleware.py', line 131 in
__call__
remember_headers = identifier.remember(environ, identity)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
repoze.who-0.9.1-py2.5.egg/repoze/who/plugins/form.py', line 59 in
remember
return rememberer.remember(environ, identity)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
repoze.who-0.9.1-py2.5.egg/repoze/who/plugins/auth_tkt.py', line 130
in remember
new_cookie_value = ticket.cookie_value()
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
Paste-1.6-py2.5.egg/paste/auth/auth_tkt.py', line 102 in cookie_value
v = '%s%08x%s!' % (self.digest(), int(self.time), self.userid)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
Paste-1.6-py2.5.egg/paste/auth/auth_tkt.py', line 99 in digest
self.user_data)
File '/var/scratch/sccdata/sites/mbms/lib/python2.5/site-packages/
Paste-1.6-py2.5.egg/paste/auth/auth_tkt.py', line 169 in
calculate_digest
+ tokens + '\0' + user_data).hexdigest()
TypeError: cannot concatenate 'str' and 'long' objects

chrism

unread,
May 7, 2008, 7:20:42 PM5/7/08
to TurboGears Trunk
I thought I fixed this in 0.9.1. You might have found an additional
bug. I've only tested under Python 2.4 using Paste 1.5, that may be
the difference. :-( There is code in repoze.who's plugins/auth_tkt.py
that is meant to cast an integer to a string on egress and back again
on ingress but it doesn't handle longs. Can you try the following
patch?

Index: repoze/who/plugins/auth_tkt.py
===================================================================
--- repoze/who/plugins/auth_tkt.py (revision 995)
+++ repoze/who/plugins/auth_tkt.py (working copy)
@@ -15,6 +15,7 @@

userid_type_encoders = {
int: ('int', str),
+ long: ('int', str),
}

def __init__(self, secret, cookie_name='auth_tkt',

chrism

unread,
May 7, 2008, 7:23:24 PM5/7/08
to TurboGears Trunk
I should probably also mention that I'm getting this list in digest
mode currently, so if you need a response fast, please cc me.

- C

chrism

unread,
May 7, 2008, 7:30:36 PM5/7/08
to TurboGears Trunk

percious

unread,
May 8, 2008, 2:58:01 PM5/8/08
to TurboGears Trunk
chris,

Thanks for the fix. Works great now.... Now if we could only get a
way to authorize on TG Controllers (ie. requires) we would be in good
shape. I will probably be writing this code at the next sprint.

cheers.
-chris

chrism

unread,
May 9, 2008, 10:52:38 AM5/9/08
to TurboGears Trunk
Isn't this what the "require" function in
http://svn.turbogears.org/projects/tgrepozewho/trunk/tgrepozewho/authorize.py
does?

Florent Aide

unread,
May 9, 2008, 10:55:37 AM5/9/08
to turbogea...@googlegroups.com
On Fri, May 9, 2008 at 4:52 PM, chrism <chr...@plope.com> wrote:
>
> Isn't this what the "require" function in
> http://svn.turbogears.org/projects/tgrepozewho/trunk/tgrepozewho/authorize.py
> does?
>

nope, what ChrisP wants is to be able to protect a full controller
without being forced to used a decorator on each exposed method.
This is something that is still needed.

Florent.

Mark Ramm

unread,
May 11, 2008, 12:24:05 AM5/11/08
to turbogea...@googlegroups.com
> nope, what ChrisP wants is to be able to protect a full controller
> without being forced to used a decorator on each exposed method.
> This is something that is still needed.

I think I have a sample of something that could work for this
somewhere, I'll try to post it up somewhere (or just add it to
tgrepozewho) in the next couple of days.

--Mark Ramm

Mark Ramm

unread,
May 11, 2008, 12:45:00 AM5/11/08
to turbogea...@googlegroups.com
I probably won't have much time to look at this until Tuesday or
perhaps even Wednesday. But I did find the code....

Here's the code snipit Jonathan sent me a while back::

from pylons.controllers.util import abort
from pylons.controllers.objectdispatch import iscontroller
from tg import expose
import inspect


def walk_controller(root_class, controller):
if hasattr(controller, 'lookup'):
lookup = controller.lookup
@expose()
def new_lookup(*args, **kwargs):
root_class._perform_validation()
return lookup(*args, **kwargs)
controller.lookup = new_lookup

for name, value in inspect.getmembers(controller):
if inspect.ismethod(value):
if iscontroller(value):
value.decoration.hooks['before_call'].append(
root_class._perform_validation
)
elif hasattr(value, '__class__'):
if name.startswith('__') and name.endswith('__'): continue
walk_controller(root_class, value)


class SecuredControllerMeta(type):
def __init__(cls, name, bases, dict_):
walk_controller(cls, cls)


class SecuredController(object):
__metaclass__ = SecuredControllerMeta

@classmethod
def check_permissions(cls):
return True

@classmethod
def _perform_validation(cls, *args, **kwargs):
if not cls.check_permissions():
abort(401, 'Unauthorized')

Basically this ensures that the classmethod check_permissions is
called (at the before_call hook) for every method in the class, or any
of it's member objects.

Obviously we could extend this so that we do identity predicate checks
specifically. But as long as check_permission returns a boolian value
we're good.

And we might be able to tweek the dispatch mechanism a bit to
eliminate the need for some of this stuff. This works, but it's not
particularly efficient at object instantiation time...

--Mark

--
Mark Ramm-Christensen
email: mark at compoundthinking dot com
blog: www.compoundthinking.com/blog

Jonathan LaCour

unread,
May 12, 2008, 9:41:09 AM5/12/08
to turbogea...@googlegroups.com
Mark Ramm wrote:

> And we might be able to tweek the dispatch mechanism a bit to
> eliminate the need for some of this stuff. This works, but it's
> not particularly efficient at object instantiation time...

We should definitely push some of this into the dispatch mechanism,
just to make the code simpler. However, since its using a
metaclass, its actually quite efficient at object instantiation
time, since all of the work occurs when the class is loaded (at
import).

--
Jonathan LaCour
http://cleverdevil.org

Mark Ramm

unread,
May 12, 2008, 3:03:40 PM5/12/08
to turbogea...@googlegroups.com
I'd like to finalize some things in tgrepozewho, and get it ready for
a release. I'm not sure what the name should be, but I'm thinking
we may want to change the name to something that's a bit more easily
identifiable for people who don't yet know where to look for
authentication/authorization stuff.

I'll add a hook in the object dispatch which enforces restrictions on
classes so that dispatch can stop as soon as a not-authorized event is
hit. We should be able to make this backwards compatible with TG1's
secure controller -- but my plan is just to check for a callable
grant_access in the controller, and evaluate that callable if it
exists. We can create a SecureResource class with two things:

1) a require property that can be set to an identity predicate. It
will default to requiring login, because that's the most common case::

require = not_anonymous()

2) a grant_access callable that returns True or False, using require.

To create custom security mechanisms for a controller you'd just need
to add a grant_access callable....

What do you think?

percious

unread,
May 12, 2008, 5:15:31 PM5/12/08
to TurboGears Trunk
My plan for the next sprint was to provide a hook in the object
dispatch in the way you describe. If you get this working, let me
know, I'll put it in production here. I think I got one of the last
items sorted out on the repoze.who side, and I have been testing it
like mad.

Personally, I prefer (one of the) ways TG1 did security, which was to
wrap the dispatch object with a function that provided the necessary
security level. I would have wanted to see this as the default way of
doing security, because it allows people to write plug-in controllers
that have no security, which can later be easily created. (subclassing
CatWalk() vs. make_secure(catwak))

cheers.
-chris
Reply all
Reply to author
Forward
0 new messages