durusmail: qp: Re: Header and footer PTL Plug-in?
Re: [Quixote-users] Header and footer PTL Plug-in?
Re: [Quixote-users] Header and footer PTL Plug-in?
2005-11-16
2005-11-22
2005-11-22
2005-11-23
2005-11-25
Re: Header and footer PTL Plug-in?
2005-11-25
2005-11-26
Re: Header and footer PTL Plug-in?
mario ruggier
2005-11-26
On Nov 25, 2005, at 4:58 PM, Michael Watkins wrote:
> * mario ruggier wrote [2005-11-25 15:43:56 +0100]:
>> Ah, so you put the access control processing behind the get_exports()
>> method. Yes, this seems a cleaner way to do it, helping also to keep
>> the more upfront UI code untangled from access control complications.
>
> I'm following, the Dulcinea (and now QP) pattern - access control is
> managed within a directory object's get_exports() method. Within UI
> methods I
> merely have to make a call to ensure_signed_in() if that method should
> be
> executable by a particular known user (possessing, or not,
> permissions).
>
>
> def SomeObjectDirectory(Directory):
>
>     def get_exports(self):
>         if get_user().is_admin():
>             yield('someadminthing', 'someadminthing', 'Process Foo',
> None)
>         if get_user().is_granted('moderate', self.someobject):
>             yield('moderate', 'moderate', 'Moderate the thing', None)
>         if get_user(): # logged in users only
>             yield('dothis', 'dothat', 'Do This Crumb', 'Do This Title')
>             # etc...
>         if not get_user(): # not signed in
>             # perhaps might need to yield up something appropriate
>             yield('register', 'not_yet_a_user', None, None)
>
>         # stuff everyone gets
>         yield('thing1', 'thing1', None, None)
>         # ...
>
>     def someadminthing(self):
>         ensure_signed_in()
>         # ...
>
>     def moderate(self):
>         ensure_signed_in()
>         # ...
>
>     def not_yet_a_user(self):
>         # here we don't want to ensure they are signed in!
>         return registration_form()
>
>     # etc...
>
> Where possible I try to avoid sprinkling user tests in the UI methods
> themselves but its not completely avoidable as there clearly are many
> times
> when you want to show some additional capability to some users
> (user.is_admin() for example) in the same stream of code dished up to
> other
> users. The permissions system certainly helps in keeping that clean.


Thanks for this example, it illustrates quite well the situation. It
seems straightforward enough, for most situations, to specify the
conditions with such a combination of if statements in get_exports(). I
think what I have in mind is to centralize all these if statements...
and just "declare" them. Now, given it seems not so complicated anyway,
it may not be worthwhile to do so, although I am not yet convinced.

Anyhow, for the sake of the exercise, let me take your export examples
and have a method, let's call it get_raw_exports(), yield them all with
some additional info (i.e. these would be a simple version of
ExportInfo objects mentioned previously). And just to be easily
compatible with current 4-tuple, I am just adding a dict object at the
end of the 4-tuple. So, on each directory we define in our site, we do
something like:

     def get_raw_exports(self):
         yield ('someadminthing', 'someadminthing', 'Process Foo', None,
             dict(allowed=('admin',)) )
         yield('moderate', 'moderate', 'Moderate the thing', None,
             dict(permission=('moderate',)) ) # Note: here only on self,
i.e. not self.someobject
         yield('dothis', 'dothat', 'Do This Crumb', 'Do This Title',
             dict(allowed=('login',)) )
         yield('register', 'not_yet_a_user', None, None,
             dict(allowed=('anon',)) )
         # stuff everyone gets
         yield('thing1', 'thing1', None, None)
         # ...

We can then have a generic method, probably on SiteDirectory or so, to
process these raw exports:

class SiteDirectory(Directory):

     def process_raw_exports(self):
         for export in self.get_raw_exports():
             if len(export)>4:
                 xinfo = export[4]
                 if xinfo.get('allowed') in ('admin',login') or
xinfo.get('permission'):
                     if (  ):
                         self.ensure_signed_in()
                         yield export[:4]
                 elif xinfo.get('anon'):
                     if (  ):
                         yield export[:4]
                     else:
                         continue
                 elif xinfo.get('whatever'):
                     ....
             else:
                 yield export[:4]

The get_exports() on this directory can then be as simple as just
calling the generic process_raw_exports() method (but may have other
tasks to do...):

     def get_exports(self):
         self.process_raw_exports()


Finally, all the exported methods themselves are unburdened of all
access checks, and may therefore proceed knowing that all
user/access/permissions conditions are met, and just deal with building
the response.

Note that the conditions used as examples here are only a few, and
process_raw_exports() will probably have to evolve into something quite
hefty. But, the more "complicated" the single and generic
process_raw_exports() gets, then the more simplifications are to be had
by the many and custom get_exports() methods, as well as the even more
numerous exported methods themselves.


mario

reply