What do you think of this? (fun mostly, don't take it too seriously ;))
It's conceptually similar to Christian's Object Model proposal, but not
as all-encompassing at this stage.
class Resource(object):
""" Base class for all resources in Trac. """
type = None
id = None
def __init__(self, id=None):
if id is not None:
self.id = id
def __repr__(self):
suffix = self.id is not None and ':' + self.id or ''
return "<Resource %s%s>" % (self.type, suffix)
class ResourceFacet(Resource):
""" A facet of a particular resource, itself also a resource """
# A tuple of the Resource classes this is a facet of.
facet_of_resources = ()
def __init__(self, id=None, facet_of_instance=None):
super(Resource, self).__init__(self, id)
assert facet_of_instance and isinstance(facet_of_instance,
self.facet_of_Type)
self.facet_of_instance = facet_of_instance
def facet_of(self, resource):
""" Determine if this object is a facet of the given
resource, or is itself of the same resource type. Accepts
either a Resource subclass or a resource ID. """
if issubclass(resource, Resource):
resource = resource.type
def walk_bases(classes):
for cls in classes:
for base in cls.__bases__:
if issubclass(base, Resource):
if base.type == resource:
return True
walk_bases((base,))
return walk_bases(self.facet_of_resources)
Example from trac/Timeline.py:
class Timeline(Resource):
""" The timeline itself. """
type = 'timeline'
class TimelineStream(ResourceFacet):
""" A timeline filter. """
type = 'timeline_filter'
facet_of_resources = (Timeline,)
class TimelineEvent(ResourceFacet):
""" A specific event in the timeline. """
type = 'timeline_event'
facet_of_resources = (TimelineStream,)
For the wiki model:
class WikiPage(Resource):
type = 'wiki'
Ooh and even more relevant:
class Ticket(Resource):
type = 'ticket'
class AbstractEnum(ResourceFacet):
facet_of_resources = (Ticket,)
Then in the tag module:
class Tag(Resource):
type = 'tag'
class WikiTag(ResourceFacet):
type = 'wiki_tag'
facet_of_resources = (Tag, WikiPage)
class TicketTag(ResourceFacet):
type = 'ticket_tag'
facet_of_resources = (Tag, Ticket)
So the IPermissionPolicy could do things like this:
def check_permission(self, username, action, resource):
""" Disallow modification of any tag or timeline related resources. """
if action == 'MODIFY' and resource.facet_of(Tag) or \
resource.facet_of(Timeline):
return False
I think some way to associate between resources and their related
objects is necessary, but that could be done at a later stage I guess.
For now I'll just add the (id, type) to the appropriate objects.
On Mon, Apr 17, 2006 at 01:13:06PM +1000, Alec Thomas wrote:
> On Sun, Apr 16, 2006 at 08:57:20PM +0200, Christian Boos wrote:
> > Christopher Lenz wrote:
> > >Am 16.04.2006 um 17:38 schrieb Alec Thomas:
> > >>On Sun, Apr 16, 2006 at 04:34:06PM +0200, Christian Boos wrote:
> > >>...
> > >>>Then, for the "resource" itself, I think we should pass the "type"
> > >>>information as well as the "id" only. Relying on the action to
> > >>>decide what kind of resource to we handle seems a bit kludgy.
> > >>
> > >>I see your point, though my reasoning was that the type is implicit in
> > >>the permission. However I guess we already have 'meta' permissions like
> > >>TRAC_ADMIN, so maybe it won't be as implicit in the future.
> > >
> > >How about passing the resource *object*, e.g. the Ticket or WikiPage
> > >instance?
> > >
> >
> > Of course, that's even better.
>
> My only reservation with this is that I currently like how you can apply
> permissions to anything:
>
> req.perm.assert_permission('CONFIG_VIEW', 'config', 'plugins')
>
> Though I guess this we'd just need to create stub objects for anything
> under resource control:
>
> class ConfigPage:
> """ Represents a configuration page. """
>
> type = 'config'
>
> def __init__(self, id):
> self.id = id
>
> > >The current permission system indeed combines resource-type and
> > >action... if we start adding actual resources/objects to the
> > >permission system, then the resource-type part should be removed,
> > >because it's (in theory, at least) part of the resource specification.
> >
> > In practice all it takes would be that each object class should define a
> > 'type' property,
> > and 'id' property, e.g.
> >
> > class WikiPage(object):
> > """Represents a wiki page (new or existing)."""
> >
> > + type = 'wiki'
> > +
> > def __init__(self, env, name=None, version=None, db=None):
> > self.env = env
> > - self.name = name
> > + self.id = self.name = name
> > if name:
> > self._fetch(name, version, db)
> > else:
> >
> > ...and so on. Not even a need for a common base class.
>
> Simple and unobtrusive. Although I guess adding a base class wouldn't be
> that much pain either, and then we could add some "convenience" methods:
>
> page.has_permission(req, 'WIKI_VIEW')
>
> Although to be honest I'm not sure this is any more convenient than
> the current:
>
> req.perm.has_permission('WIKI_VIEW', page) ??
>
> Anyway, go with simple first I think :)
>
> As a convenience, the permission methods could support a shorthand form:
>
> req.perm.has_permission('VIEW', page)
>
> Deriving the prefix from the page.type.
>
> > Well, I'm sure a full fledge "recursive role system" must be worth
> > waiting for post-1.0.
> > However, if someone comes with a simpler approach for this, which seems
> > to be sound,
> > simple and appears to be a step forward from what we have, then why not
> > adopt it?
>
> That was exactly my motivation for this patch. The idea was to make it
> as backwards compatible as humanly possible, while adding good
> permission control.
>
> To that end, I'd suggest keeping the current permissions (WIKI_VIEW,
> etc.) and the default IPermissionStore system, to lessen the impact on
> users.
>
> I do agree though, that a full revamp of the permission system would be
> ideal, but very disruptive and a great deal of work.
>
> > >Still, I'd be in favor of you creating a sandbox branch for this work
> > >(but only if it doesn't distract you from the workflow work too much ;-)
>
> Sounds good, I'll create it today ;)
>
> > Yes, and targeting it for 0.11...
>
> I'd be +1 for this, obviously. The criteria being:
>
> - Simple, but flexible
> - Unobtrusive
> - Backwards compatibility
>
> For 1.0, all bets are off (?), but as with Spam control, I think useful
> permission control would be better sooner than later.
>
> So, regarding terminology? :) I suggest calling them 'resources', as
> 'objects' is very generic, and connotative of having some extra
> functionality that may not exist. Not everything the security system
> applies to will refelect this, eg. about/config pages.
>
> user X has permission to user resource Y
>
> --
> Evolution: Taking care of those too stupid to take care of themselves.
> _______________________________________________
> Trac-dev mailing list
> [email protected]
> http://lists.edgewall.com/mailman/listinfo/trac-dev
>
--
Evolution: Taking care of those too stupid to take care of themselves.
_______________________________________________
Trac-dev mailing list
[email protected]
http://lists.edgewall.com/mailman/listinfo/trac-dev