user roles

Derek Atkins warlord@MIT.EDU
03 Jan 2001 18:39:51 -0500


David Merrill <dmerrill@lupercalia.net> writes:

[snip]

> Ahhh. Pseudo-code is so much more precise than English can ever hope
> to be. Thank you. I see now that you are including an additional level
> of abstraction, by separating "group" from "role". My concept of
> "role" is analagous to AclEntry, and I don't have a separate "group"
> concept.

The only thing I forgot to mention was that different object contain
acls:

Account ::= {
	...
	Acl	acl
}

Transaction ::= {
	...
	Acl	acl
}

> I can also see a clear benefit to your approach. It is a bit more
> complex to implement because of the additional layer, but I think it
> is still manageable.
> 
> In every other way, we are already in agreement. Good.

Good :)

> > Could you please explain what "referential integrity rules" there are
> > and how they apply?
> 
> In your IDL, you have a GUID that can be *either* a user's GUID or a
> group's GUID. Referential integrity can't say that it can be either
> one or the other; it must be exactly one of them. But we can just do
> away with the refint on that field and there is no problem.

Um, ok.  Basically, what I was trying to get at is the equivalent of
a union...  Perhaps someting like:

	enum	{USER, GROUP}
	GUID	userID
	GUID	groupID

The point being a means to have (one of) either group or userid in a
single table row.

> Here are table structures that implement your acl concept:
> 
> 
> USER
> ----
> dbuser_guid
> 
> 
> GROUP
> -----
> group_guid
> 
> 
> USER_GROUP
> ----------
> dbuser_guid
> group_guid

This is a mapping of users into groups, right?  You use this table to
add users to groups:

group_guid	dbuser_guid
1		warlord
1		linas
1		dlb
2		warlord
2		dmerrill

> ACL
> ---
> acl_guid
> set of permissions
>
> USER_ROLE
> ---------
> guid (either user or group)
> acl_guid

So, it looks like you've split what I called an AclEntry into two
parts.  You can map a set of users and groups to a set of permissions.
However you still don't have what I called an Acl, which is a list of
AclEntries.  I'd like to assign a different set of permissions to a
set of users/groups when they try to access a particular object.  For
example, I might want to represent this set of permissions in a single
ACL:

	warlord		Read, Write, Admin
	dmerril		Read, Write
	groupX		Read

Then in the Transaction, Account, Split, or whatever, you reference an
Acl.  E.g., I'd reference the above ACL from the account
"Account::Payable".

> user_role is where the fun stuff happens. You have defined your users;
> you have defined roles/acls which specify a set of permissions; you
> have assigned each of your users to a group or groups. Then, in a
> completely separate structure, you can assign any set of acls to a
> user or to a group. And a user inherits all the permissions assigned
> via the acls which have been given to him or to his groups.

I think I follow you so far.  I can see how you can define AclEntries:
I can define a set of users or groups which all have the same set of
permissions.  I think we need one more table that allows us to combine
sets of what you call USER_ROLES into a single ACL that can be
referenced by Transactions, Accounts, splits, etc.:

ACL
---
acl_guid
acl_number

Or perhaps you can just assign one more entry to the USER_ROLE
table, the acl_number:

USER_ROLE (aka ACL)
---------
acl_number
acl_guid
guid (either user or group)

Then I can make an ACL that looks like:

acl_number	acl_guid	guid
1		1		1
1		1		2
1		2		3
1		3		1
2		1		1
2		2		2

This defines two acls.  Acl #1 looks like:
	guid	perms
	1	1, 3
	2	1
	3	2

And acl #2 looks like:
	1	1
	2	2

Where the guid can be either a user or a group (how do you actually
tell?), and the permissions are a set of permissions

> This approach is more flexible for administrators in that it allows
> them to grant or revoke entire sets of permissions across groups and
> users by changing the acl. You could also do that in the simpler
> design, but you would have to edit each role directly, because the
> "acl" concept is tied directly to the group. Your approach is easier
> on administrators willing to understand them, but probably harder to
> understand.

See, I don't think it's hard to understand.  You just have to realize
that an ACL has no meaning by itself, it is associated with some
specific data object.  Indeed, an ACL is specifically tied to a
particular piece of data that is being protected in some way.

So you just need to present the model this way:
	1) You have a set of users
	2) You can create groups and assign user(s) to group(s)
	3) You have an object (e.g. a specific Account) to protect
	4) You want to assign permissions on that specific Account
	5) You build an acl for the Account where you enumerate:
		a) each user or group that needs access to the Account
		b) what specific types of access each user or group needs

There you go, you've just defined your ACL for that Account. :) Now
repeat the process for every object.

[snip]
> Yes, they are assigned directly.

Like I said, this is wrong.  ACLs can't live by themselves; they have
no meaning.  ACLs have to be tied to a particular piece of data.
Otherwise you have the dangling question: when (or how) do you apply
the permissions of an ACL?

> > For example, you have a role (group) of users called "accounts
> > receivable data entry".  Obviously, your team of workers can change
> > over time, so membership in this group will change as well.  Then you
> > add that group to the acl on a set of accounts, where each account may
> > assign different permissions to that particular group.  For example,
> > you probably don't want to grant access to the payroll accounts to
> > this group.  In order to have this functionality, permissions for the
> > group must be tied to the object being protected, not to the group
> > itself.
> 
> I don't think this is true. Maybe in a standard acl design, but not in
> a database permissions design. It may not be as manageable in some
> environments, but you can accomplish all the same end results. It just
> may take more work.

Ok, using your design how would you accomplish the above permission
definition?  I still don't see how it's done.  Keep in mind I also
don't have the full schema in front of me, only the snippets you've
sent so far ;)

> > But you need to be able to set the rights based on the various objects
> > in the system.  How would you assign the rights to, say, read current
> > transactions but not previous transactions?
> 
> One way or another you would have a flag in the role record to set it
> on or off for that role/group.

See, I see it the other way around.  You set the ACLs on each object
to get the permissions you want.  So, your old transactions would get
a different ACL than your new transactions.

> Yes, the permissions are predefined in the sense that defaults are
> installed. But they are fully configurable. I'm not proposing that
> they be hard coded in any way.

Um....

> It is difficult to discuss this whole issue when we are coming from
> such different backgrounds and seeing things through different
> filters.

Perhaps we should phone each other to discuss this?  I think it might
be a higher-throughput discussion, and we can hopefully get beyond (or
explain) our different viewpoints. ;)

>  But if I interpret your proposal correctly, there is only one
> difference: the ability to have a set of permissions, a role, defined
> separately from the groups who use them. 

I suppose...  I mean, how often are you going to want to define "read"
or "read,write" permissions?  But I'm talking more than that...
Remember that I don't have the concept of 'role' in my model (or if I
do, I'm clearly calling it something else).

> So, you can define a set of
> permissions to a set of accounts, and then assign them to multiple
> groups. In my design, you would have to set each group's permissions
> individually. I don't provide for a set of permissions being separate
> from a group/role (which are the same thing in my model).

Well, I want to be able to assign a set of permissions to EACH user or
group contained in an ACL for an account, and do so for every account
in the books.  I also want to do the same thing for every transaction
in each account, set an acl individually.

One thing I still don't understand from your methods:  How do you
assign an ACL to a data object (e.g. an Account)?

> I'm happy to go with the more complex design as long as we're sure the
> additional functionality is worth the additional complexity.

Well, _I_ think the added functionality is worth it. ;)

-derek

-- 
       Derek Atkins, SB '93 MIT EE, SM '95 MIT Media Laboratory
       Member, MIT Student Information Processing Board  (SIPB)
       URL: http://web.mit.edu/warlord/    PP-ASEL-IA     N1NWH
       warlord@MIT.EDU                        PGP key available