Greetings.
[1] http://docs.pylonsproject.org/projects/pyramid/en/1.2-branch/narr/urldispatch.html#route-factories
> --
> You received this message because you are subscribed to the Google Groups
> "pylons-discuss" group.
> To post to this group, send email to pylons-...@googlegroups.com.
> To unsubscribe from this group, send email to
> pylons-discus...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/pylons-discuss?hl=en.
>
Ok, but if you want to show the list of tasks in the index user page,
how do you check the tasks permission, for example to show a icon near
the task description, in case you can edit that task?
A lot of thanks.
PD: My conclusion is I need to created a role or group attribute in the
user-task relation, to see if the user has the correct role/group
assigned to this object...
My context factories can be used in a hybrid way. As regular context factories they retrieve the object according to matchdict. But they can be passed the object as well and then just compute the permission. So in the Index i'd loop over all possible tasks and ask the factories for each route whether the User gas this permission.
Am 16.02.2012 17:36 schrieb "Antonio Beamud Montero" <antonio...@gmail.com>:
El 16/02/12 16:44, Robert Forkel escribió:
i went with a custom context factory [1] per route; i.e. i have routes
for patterns like "/task/{id}/edit" or "/task/{id}/view" and register
context factories for these which retrieve the task object from the db
and compute the permissions, i.e. attach an appropriate __acl__ object
to the task object.
regards
robert
[1] http://docs.pylonsproject.org/projects/pyramid/en/1.2-branch/narr/urldispatch.html#route-factories
Ok, but if you want to show the list of tasks in the index user page, how do you check the tasks permission, for example to show a icon near the task description, in case you can edit that task?
A lot of thanks.
PD: My conclusion is I need to created a role or group attribute in the user-task relation, to see if the user has the correct role/group assigned to this object...
On Thu, Feb 16, 2012 at 4:12 PM, Antonio Beamud Montero
<antonio...@gmail.com> wrote:
Hi, what's the best way to implement a permission per object in pyramid
using SQLAlchemy to store users info, and using url distpatch.
For example, If a user has three tasks assigned, he can edit two of them,
but only view the 3rd, or view tasks of other users (if they want), but not
edit them.
Greetings.
--
You received this message because you are subscribed to the Google Groups
"pylons-discuss" group.
To post to this group, send email to pylons-discuss@googlegroups.com.
To unsubscribe from this group, send email to
pylons-discuss+unsubscribe@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/pylons-discuss?hl=en.
--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To post to this group, send email to pylons-discuss@googlegroups.com.
To unsubscribe from this group, send email to pylons-discuss+unsubscribe@googlegroups.com.
How do you do this?
--
Mike Orr <slugg...@gmail.com>
class AuthzContext(object):
implements(IAuthzContext)
__object_class__ = None
def __init__(self, request):
self.request = request
self.object = None
# make sure the reified attribute 'user' is instantiated
self.user = request.user
#
# while it is the main responsibility of a AuthzContext to determine
# the correct context object and attach ACEs to it, there's a shortcut
# which allows passing in the context object as attribute of the
# request. this mechanism can be used to compute permissions
"in advance"
# i.e. without actually preforming a request. this allows us to keep
# view permissions and links in sync.
#
if getattr(request, 'authz_object', False):
self.object = request.authz_object
else:
self.object =
self.__object_class__.get(int(request.matchdict['id']), default=None)
if not self.object:
raise HTTPNotFound()
self.object.__acl__ = []#[(Allow, 'group:admin', ALL_PERMISSIONS)]
#
# call the convenience methods which may be used to set ACEs:
#
if self.allow_if():
self.allow()
else:
self.deny()
def allow_if(self):
return False
def allow(self, permission=None):
if self.request.user:
self.object.__acl__ = [(Allow, self.request.user.login,
permission or getattr(self, 'name', 'none'))]
else:
# no user logged in but we still have to allow access:
self.object.__acl__ = [(Allow, Everyone, permission or
getattr(self, 'name', 'none'))]
def deny(self, permission=None):
if self.request.user:
self.object.__acl__ = [(Deny, self.request.user.login,
permission or getattr(self, 'name', ALL_PERMISSIONS))]
else:
self.object.__acl__ = [(Deny, Everyone, permission or
getattr(self, 'name', 'none'))]
def context_factory(authz_context):
"""We must make sure a new AuthzContext instance is created for
each request.
Since __init__ must not return anything, we must use a helper function to
mediate.
"""
def context(request):
_authz_context = authz_context(request)
return _authz_context.object
return context
def has_permission_on_object(permission, request, object_):
"""Compute object-specific permissions ahead of time, i.e. without
the object
being determined from the request's properties. We still use the context
factory to assign the same __acl__ to the object as would happen
with a "real"
request. Thus, use this function to check whether a user (detemined by
request) will have access to a specific action (determined by permission) on
an object_.
"""
context = request.registry.queryUtility(IAuthzContext,
name=permission, default=None)
if context:
request.authz_object = object_
res = has_permission(permission,
context_factory(context)(request), request)
request.authz_object = None
else:
res = has_permission(permission, RootFactory, request)
return res
> --
> You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
> To post to this group, send email to pylons-...@googlegroups.com.
> To unsubscribe from this group, send email to pylons-discus...@googlegroups.com.
class Task(Base):
...
users = orm.relationship(UserTask,
backref='tasks')
def __acl__(self):
acl = []
for o in self.users:
acl.append((Allow, o.user.username, o.permission))
return acl
class UserTask(Base):
__tablename__ = 'user_task'
task_id = Column(Integer, ForeignKey(Task.id), primary_key=True)
user_id = Column(Integer, ForeignKey(User.id), primary_key=True)
user = user = orm.relationship("User", backref="tasks")
permission = Column(Unicode(80))
And to show in my index page, all my tasks, with an edit link (if
apply), we can check the permission with:
d = {}
q = DBSession.query(Task).join('user', 'users')
res = q.filter(and_(User.username = request.user.username)
for t in res:
d[t.id] = None
if has_permission('edit', t, request):
d[t.id] = 'edit'
return d
I'll test this weekend... any drawbacks?
To manage url's like /tasks/1/edit I need a Factory, of course.
Greetings.
On Fri, Feb 17, 2012 at 1:52 PM, Antonio Beamud Montero
<antonio...@gmail.com> wrote:
> El 17/02/12 10:33, Robert Forkel escribió:
First, I implement a root factory with a group_finder method.
Something like this:
class RootFactory(object):
__acl__ = [
(Allow, Everyone, 'view'),
]
def group_finder(self, userid):
return []
This is registered with the configuration as the default factory. I
specify a callback for my authentication policy that delegates the
group_finder to the current context.
def group_finder(userid, request):
return request.context.group_finder(user_id)
...
authn_policy = AuthTktAuthenticationPolicy(
'sosecret', callback=group_finder)
By default, this calls the RootFactory group_finder which assigns no
additional roles roles/groups.
For specific routes I add factories to load the appropriate task
instance. Since the group_finder is context aware it calls the
group_finder method of the task object.
My ACLs are defined at class level in the model
__acl__ = [
( Allow, 'group:owner', 'edit')
]
def group_finder(self, user_id):
if user_id == self.owner_id:
return ['group:owner']
else:
return []
You can check the groups of a user by calling the group_finder method
of an instance.
Writing this, it might make sense to have a mix-in class which
implements a default group_finder and has_group method which you could
throw into your models.
This approach has worked for me, but I doubt it's ideal. I'd love to
see more detail on instance level authorization added to the
documentation.
Brian
I'd love to
see more detail on instance level authorization added to the
documentation.
El 16/02/12 16:44, Robert Forkel escribió:
i went with a custom context factory [1] per route; i.e. i have routes
for patterns like "/task/{id}/edit" or "/task/{id}/view" and register
context factories for these which retrieve the task object from the db
and compute the permissions, i.e. attach an appropriate __acl__ object
to the task object.
regards
robert