Re: Pattern Approach to User permissions?
Re: Pattern Approach to User permissions?
- Subject: Re: Pattern Approach to User permissions?
- From: Jonathan Rochkind <email@hidden>
- Date: Tue, 2 Mar 2004 20:14:27 -0600
I've implemented a system that is very flexible, but rather
complicated, and really ends up being rather more expensive than I'd
like. I'm not sure this was the best way to do this, but I'll tell
you what I've done. [One of the hardest parts was coming up with the
right terminology! At this point if I had to write it over, I'd use
different terms, which I'll now use here]. [I didn't research any
existing systems before doing this, so odds are there was a better
way to do it; but I'm not sure; I'm not sure it does exactly what
y'all are looking for either].
The EOEnterpriseObject at the heart of it all, let's call it a
UserObjectRoleRegistration. The idea is to register a User as having
an arbitrary String "role" on an arbitrary EOEnterpriseObject.
It's attributes:
objectEntity: String
objectPK: Integer
userID: Integer (foreign key to User)
role: String
This will only work for objects with single integer primary keys.
Since we want to attach it to any arbitrary object, we can't use an
actual EORelationship---but see how the entity and the pk give us
enough information to figure out exactly what object is recorded in
this UserPermissionRegistration. (I use
EOUtilities.faultWithPrimaryKeyValue, to create a fault to the
registered object in awakeFromFetch on UserObjectRoleRegistration).
For instance, I can use it to record which users "own" a certain
Document, with a records that look like this:
objectEntity: Document
objectPK: 1923 [Document with pk 1923]
userID: 3434 [User with pk 3434 is registered]
role: "own" [as having the 'own' role on Document 1923].
[The system is actually somewhat more complex than THAT, because I
support Groups having these registrations, not just Users. The code
gets wacky].
I have a reusable component that takes bindings for "role" and
"enterpriseObject", and then allows you to add and remove users
(adding and removing UserObjectRoleRegistrations).
Now let's say we have a WOComponent for editing Documents. Perhaps we
only want users with the 'own' role on the specified document to have
access to the page. The component can over-ride appendToResponse to
check if a user has the proper role on the specified document, and
provide an 'access denied' page if not (or provide a 'login' page if
no user is yet logged in, and then check again after login).
Really, my system is even more complex. I also have objects we'll
call PermissionQualification, which implement an interface with one
method, "public boolean isMetByUser(User u);" So one type of
PermissionQualification would require a user to have a certain role
on a certain object, and then return true/false depending on whether
the User passed in does. So the access-checking WOComponent's
sub-class a common superclass, allowing them to simply implement a
method:
"public PermissionQualification qualificationRequiredForAccess();"
If over-ridden, the super-class will automatically see if the
logged-in user meets the PermissionQualification returned, and
restrict access to the page based on that. Once I started writing
these PermissionQualifications, I realized that there are other types
of useful PermissionQualifications that have nothing to do with the
UserObjectRoleRegistration.
And then my EOEnterpriseObjects often define a set of
PermissionQualifications. For instance, Document might have a method
"public PermissionQualification qualificationForOperation_edit();"
which returns the PermissionQualification needed to edit a particular
Document instance.
Common things we might want to do with the
UserObjectRoleRegistrations are: Restrict access to a page based on
them; Restrict access to a button _on_ a page based on them. [Wrap
the button in a WOConditional that says the user has to meet a
certain PermissionQualification]; Filter a list [We have a list of
Documents, and want to filter out only the Documents for which the
logged in user meets PermissionQualification returned by
theDocument.qualificationForOperation_edit()]; list all the users
who have a certain role on a certain EO [A list of all users with
'own' UserObjectRoleRegistrations on a certain Document].
These things end up getting expensive, since we need to go to the
database to look up UserObjectRoleRegistrations. So I have several
caching systems in place, to cache already looked up
UserObjectRoleRegistrations, so a db trip is not neccesary. But then
you've got to make sure to invalidate/refresh that cache when you
make changes (adding or removing UserObjectRoleRegistrations).
The whole thing gets really complicated, and still is quite a bit
more expensive than I'd like. And let's not even talk about trying to
build an EOQualifier to fetch Documents from the database that are
'own'ed by a User with lastname "Smith" (to execute a user-specified
search). (The SQL sub-query qualifier from Project Wonder is
invaluable, since there is no relationship to follow). But... it
works. I'm using it in my deployed apps. It's remarkably flexible.
But it's occasionally a pain. I dunno.
--Jonathan
At 8:07 PM -0500 3/2/04, Arturo Pirez wrote:
On Mar 2, 2004, at 4:45 PM, Kieran Kelleher wrote:
I am trying to decide how best to incorporate user-based
permissions for selecting (viewing), inserting (adding), updating
(editing) and deleting EO's into my object model design.
I'm also wrestling/designing such a system. I've decided to pattern
mine after JAAS but beyond that I'm not certain how to proceed.
In JAAS you have a Subject toMany Principal toMany Permission. In
both your and my model that falls short in that we both want to
manage Resources. A Subject is, essentially, a collection of
Principals. Each Principal can be interpreted as a role of some
sort (kind of like group permissions). In the base JAAS model, a
Permission includes a kind of Resource class and an action that can
be performed against it.
There are examples of how to extend JAAS to include resource
instance-based information. See this document over at IBM
http://www.ibm.com/developerworks/java/library/j-jaas/. In any
case, the JAAS arena may give you some ideas on how to proceed.
In my case, I'm not sure that I want the coupling between the
permissions model and my other models that you're thinking about. I
want my security framework to be reusable to other applications as
well. What I would like would be to use something like eogenerator
to create java.security.Guard-wrapped EOs. Does anyone know if it
can be modified to do so? Alternatively, make a subclass of
EOGenericRecord that overrides the validate methods to enforce
permissioning. Then I figure I'll need a permission/security
oriented version of WOComponentContent to wrap around things.
Thoughts?
----
WO in philadelphia - wanna cheesesteak with that?
Please visit webobjects.meetup.com.
_______________________________________________
webobjects-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/webobjects-dev
Do not post admin requests to the list. They will be ignored.
_______________________________________________
webobjects-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/webobjects-dev
Do not post admin requests to the list. They will be ignored.