I've just pushed some code for using role-based authorization in 0.9.x.
I thought I'd take a few minutes to explain it.
Roles are identified by 32-char strings. Rights to do things are granted
to roles, /not/ to individuals (for now). You can give rights to an
individual by adding them to a role. We have a table in the database,
user_role, that maps users (by id) to roles.
Note that "roles" are similar to "groups" in POSIX systems; but we
already have groups in StatusNet, which are orthogonal, so I've used the
term "role" instead (which I think is clearer, anyways).
Non-local users cannot exercise any additional rights, for the simple
reason that we don't authenticate them.
Rights are constants in a new class, 'Right' (lib/right.php). The value
of the rights are strings right now; they could be integers if we need
them to be. The constant names are verbs or verb phrases, like
"deleteOthersNotice" or "banUsers".
We have two pre-defined roles in the system:
* 'moderator' is someone who manages the social life of an instance.
They have (or will have) rights to do things like delete other
users' notices, ban users, block users from posting to the public
timeline, deleting another users' account, promoting a member of
any group to group admin, marking a notice as spam, sending a
direct message to anyone, granting or revoking roles from other users.
* 'admin' is someone who handles the technical parts of an instance.
Their primary right is to change configuration settings (like the
theme, name of the instance, etc.) (Yes, there's a slight overlap
with the "group admin" name. I guess we could say "site admin" and
"group admin" to distinguish.)
There's no reason that one person couldn't have both of these roles
simultaneously; on small systems it makes a lot of sense.
Which roles can execute which rights are defined in User::hasRight().
It's just a switch() statement right now. It's strictly forbidden (by
me) for any code to try to do roles-to-rights mapping itself; instead it
must use this helper function. This way, as the authorization framework
matures, most code will be insulated from the changes.
There is not an interface for granting roles to users; there will be by
the time we release 0.9.x.
Plugins can define their own roles, and should probably use prefixed
strings to prevent namespace collisions (e.g. "MyPlugin::registeredUser"
rather than just "registeredUser" or "reg" or "registered"). Plugins can
also define their own rights, which should also be prefixed strings and
should probably also be defined constants (so: class MyPlugin { const
canUse = "MyPlugin::canUse"; ... }.
Plugins can hook the UserRightsCheck event to describe the rules for
their own roles and rights/./ So a plugin with its own authorization
stuff might look something like this:
class MyPlugin
{
const canUse = "MyPlugin::canUse";
function onEndNoticeSave($notice)
{
$user = common_current_user();
if ($user->hasRight(MyPlugin::canUse)) {
// do something here
}
}
function onUserRightsCheck($user, $right, &$result) {
if ($right == MyPlugin::canUse) {
$result = $user->hasRole("MyPlugin::registeredUser");
return false; // done processing!
}
return true; // unchanged!
}
}
Note that the plugin uses User::hasRight(), even though it defines the
rights mapping itself later.
Event handlers can also hook UserRightsCheck /to override the default
rights system./ So, if on your system, /anyone /can delete another
person's notice (say), you could do this:
function FreeForAll($user, $right, &$result)
{
if ($right == Right::deleteOthersNotice) {
$result = true;
return false; // no further or default processing
}
return true;
}
Event::addHandler('UserRightsCheck', 'FreeForAll');
Note that the return value from rights-modifying code may be
counter-intuitive.
Future versions of the software (post-0.9.x) may have the following
features, depending on demand:
* Grant of rights to users as well as roles.
* A finer-grained system of built-in roles. I vastly prefer a very
simple system; I doubt 99% of sites will need more than
"moderator" and "admin".
* Use of the rights system for some of the existing "rights" --
things that only registered users can do that anonymous users
can't, for example.
* Storing the mapping of role-to-right in the database.
* Allowing some super-user to re-jigger the rights mappings in some
kind of Web interface.
Thoughts? Ideas, feelings, responses?
-Evan
--
Evan Prodromou
CEO, StatusNet, Inc.
e...@status.net - http://identi.ca/evan - +1-514-554-3826
_______________________________________________
StatusNet-dev mailing list
StatusNet-dev@lists.status.net
http://lists.status.net/mailman/listinfo/statusnet-dev