Roles-Based Security: Difference between revisions
Rwolverine (talk | contribs) No edit summary |
Rwolverine (talk | contribs) |
||
| Line 71: | Line 71: | ||
PRIMARY KEY (`user_id`), | PRIMARY KEY (`user_id`), | ||
KEY `login` (`login`) | KEY `login` (`login`) | ||
) </sql | ) </sql> | ||
Note that we can off-course add more fields like “email” but currently they are irrelevant. | Note that we can off-course add more fields like “email” but currently they are irrelevant. | ||
| Line 174: | Line 174: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Here, you see a new type of attribute “atkProfileAttribute” that does all the magic. This attribute is going to list all the modules and each action available and allow you to grant them to the profile (so the users belonging to that profile can do the action). | Here, you see a new type of attribute “atkProfileAttribute” that does all the magic. This attribute is going to list all the modules and each action available and allow you to grant them to the profile (so the users belonging to that profile can do the action). | ||
==Configuration of atk== | ==Configuration of atk== | ||
Revision as of 13:19, 7 December 2007
|
ATK Howto: Roles-Based Security
|
How to Define Role-Based Security using the ATK.
Introduction
This tutorial explains first how to setup the admin part for the security (how to create a user, how to define what he/she can do...). Once we have created this access right framework, we are going to configure ATK so it actually uses these access rights. On ATK, each module allows several actions, by default, these actions are “admin”, “add”, “delete”, “edit”. Creating new actions is outside the scope of this how to (link to something)?
The security mechanism is based on “Entities”. An entity is a group of users. It can be a department, a group, a profile, a role, depending on how you want to name them. On this document, we are going to call them “profile”, but the name doesn't matter much, as long as you understand the principle.
For each profile, the administrator is going to grant different “permissions” on all or some actions to each module of the application. Each profile might have. Normal users might be able to only “admin” a node, while power users will also be able to “add”, “edit” and “delete” records in the node. This isolates security privileges from individuals thereby simplifying and streamlining security management.
There are 2 common options for managing users and profiles. Either a user is part of one profile, or a user is part of many (one or more) profiles. In this tutorial we will explain both methods.
User is part of one profile
Please note the atk demo application has a lesson (Lesson 5)that deal with this configuration exactly. In case you have any difficulties – please refer to the code, comments and tables in the demo application.
First, we are going to install the framework (the users, profiles...) needed to manage this security scheme and see how to configure atk to manage these items (after all, that's going to be content stored in table, and therefore is going to be managed by atk as nodes and modules).
Node Structure Our new module is called “users”. So we add a new sub-directory in the modules directory, and add the module.inc file first. We need two nodes: a user node and a profile node.
************************** users/module.inc **************************************
class mod_users extends atkModule
{
function getNodes()
{
/* register nodes */
registerNode("users.user", array("admin", "add", "edit", "delete"));
registerNode("users.profile", array("admin", "add", "edit", "delete"));
}
function getMenuItems()
{
/**
* The next line adds a submenu called 'users' to the main menu.
*/
menuitem("users");
menuitem("users", dispatch_url("users.user", "admin"),"users");
menuitem("groups", dispatch_url("users.profile", "admin"),"users");
}
}
************************** users/module.inc **************************************
Users
The user has a login and password and belongs to a profile.
First you need to create the following table: <sql> CREATE TABLE `user` ( `user_id` int(11) NOT NULL default '0', `login` varchar(25) NOT NULL default , `name` varchar(50) NOT NULL default , `password` varchar(50) default NULL, `profile_id` int(11) default NULL, PRIMARY KEY (`user_id`), KEY `login` (`login`) ) </sql>
Note that we can off-course add more fields like “email” but currently they are irrelevant.
Then we add the user node:
************************** users/class.user.php **************************************
useattrib("atkemailattribute");
useattrib("atkpasswordattribute");
userelation("atkonetomanyrelation");
userelation("atkmanytoonerelation");
class User extends atkNode
{
function User()
{
$this->atkNode("user", NF_ADD_LINK);
$this->add(new atkAttribute("user_id", AF_AUTOKEY));
$this->add(new atkAttribute("name", AF_OBLIGATORY|AF_SEARCHABLE));
$this->add(new atkAttribute("login", AF_OBLIGATORY|AF_UNIQUE|
AF_SEARCHABLE));
$this->add(new atkPasswordAttribute("password",true,AF_HIDE_LIST|
AF_PASSWORD_NOVALIDATE));
//link to profiles
$this->add(new atkManyToOneRelation("profile_id", "users.profile", AF_RELATION_AUTOLINK|AF_HIDE_ADD));
$this->setOrder("name");
$this->setTable("user");
}
function descriptor_def()
{
return "[name]";
}
}
************************** users/class.user.inc **************************************
As you can see, there is a link between each user and a profile.
Profile Here too, you have to create DB tables (this time two tables, one for the profile, the other to store the access rights). <sql> CREATE TABLE `profile` ( `profile_id` int(11) NOT NULL default '0', `name` varchar(100) NOT NULL default , PRIMARY KEY (`profile_id`) )
CREATE TABLE `access` ( `node` varchar(100) NOT NULL default , `action` varchar(25) NOT NULL default , `profile_id` int(11) NOT NULL default '0', PRIMARY KEY (`node`,`action`,`profile_id`) ) </sql>
And add the profile node:
************************** users/class.profile.inc **************************************
useattrib("atkdummyattribute");
useattrib("atkprofileattribute");
class profile extends atkNode
{
function profile()
{
$this->atkNode("profile", NF_EDITAFTERADD|NF_NO_VIEW);
$this->add(new atkAttribute("profile_id",AF_AUTOKEY));
$this->add(new atkAttribute("name",AF_OBLIGATORY|AF_UNIQUE|
AF_SEARCHABLE, 50));
$this->add(new atkDummyAttribute("profile_explanation",text
("profile_explanation"),AF_HIDE_LIST|AF_HIDE_ADD));
$this->add(new atkProfileAttribute("accessrights",AF_HIDE_LIST|
AF_HIDE_ADD|AF_BLANKLABEL));
$this->setTable("profile");
$this->setOrder("name");
}
function descriptor_def()
{
return "[name]";
}
}
************************** users/class.profile.inc **************************************
Here, you see a new type of attribute “atkProfileAttribute” that does all the magic. This attribute is going to list all the modules and each action available and allow you to grant them to the profile (so the users belonging to that profile can do the action).
Configuration of atk
We are almost done and the only missing step is to tell atk to use the access rights defined in these tables. For that, you need to modify the file config.inc.php : 1) you need to change the config_authentication and set it to “db”
// $config_authentication = "none";
$config_authentication = "db";
2) You need to tell atk what the tables that store the access rights are:
$config_auth_usertable = "user";
$config_auth_userfield = "login";
$config_auth_passwordfield = "password";
$config_auth_leveltable = "user";
$config_auth_levelfield = "profile_id";
$config_auth_accesstable = "access";
That’s it! Now you can login to the application and review the screens that atk generates for you. All the functionality is already there for you to use.
User can be part of one or more profiles
This method is a bit more advanced, and allows you to configure different profiles, when each profile has different set of permissions. For example – the “normal” profile has the “admin” and “edit” permissions, and the “power” profile has the “delete” permission. A user with both “normal” and “power” profiles will be able to “admin”, “edit” and “delete”.
ATK can support this configuration as well, but some changes (to the above installation) needs to be made.
User-Profile In order to established the relationship between 1 user and many profiles, we need a supporting table. <sql> CREATE TABLE `userprofile` ( `user_id` int(11) NOT NULL, `profile_id` int(11) NOT NULL, PRIMARY KEY (`user_id`,`profile_id`) ) </sql> As you can see, this is a simple “many-to-many” support table.
Here is the “userprofile” node:
************************** users/class.userprofile.inc **************************************
userelation("atkmanytoonerelation");
class userprofile extends atkNode
{
function userprofile ()
{
$this->atkNode("userprofile", NF_NO_EDIT);
$this->add (new atkManyToOneRelation("user_id", "users.user", AF_PRIMARY));
$this->add (new atkManyToOneRelation("profile_id", "users.profile", AF_PRIMARY));
$this->setTable("userprofile");
}
/**
* Return record descriptor (for use in relations etc.)
* @return String A template containing fieldnames between brackets.
*/
function descriptor_def()
{
return "[user_id] , [profile_id]";
}
}
************************** users/class.profile.inc **************************************
This node reflects the userprofile table structure, with 2 mant-to-one relationships – to users and to profiles. Theoretically – (just to emphasis the meaning of the node) you can ask this node for all profiles of the user_id=“1”, or all users that are part of the profile_id=”2”.
Users In the user DB table, the “profile” filed is no longer needed. This is because we will now have a separate table managing the connection between the users and the profiles.
Further more – the “profile” relation attribute in the “users” node is no longer needed, and is replaced by a special relation “atkManyBoolRelation” :
************************** users/class.user.inc **************************************
$this->add(new atkManyToOneRelation("profile_id", "users.profile", AF_RELATION_AUTOLINK|AF_HIDE_ADD));
$rel = &$this->add(new atkManyBoolRelation("profiles", "users.userprofile", "users.profile", AF_HIDE_LIST|AF_MANYBOOL_AUTOLINK));
$rel->setLocalKey("user_id");
$rel->setRemoteKey("profile_id");
************************** users/class.user.inc **************************************
This will allow us to edit the user, and assign the user to one or more profiles.
Configuration of atk We already told atk (in the previous section”) what is our users / profiles tables. We now need to update the configuration, and tell atk that there is a now table to use :
$config_auth_usertable = "user";
$config_auth_userfield = "login";
$config_auth_passwordfield = "password";
$config_auth_userpk = "user_id";
$config_auth_leveltable = "userprofile";
$config_auth_levelfield = "profile_id";
$config_auth_userfk = "user_id";
$config_auth_accesstable = "access";
With these 3 new lines we are telling atk to look for the profile information for each user in the “userprofile” table, while also mentioning the names of the fields in this table.
That’s it!
Now you can login to the application and review the screens that atk generates for you. First add 2 new profiles. Than add a new user. After that edit the user, and you can see that a new control is added, allowing you to assign 1 or both profiles for the user.
The DB tables are updated accordingly.