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

Reply via email to