access control
Archived from the Xataface Users forum.
compudude86 — Mon Sep 25, 2006 8:56 am
hi,
i want to make it so only certain people can edit and other people can only view, based on the user/password they give. i was thinking to use mysql users to do this-for compatibility purposes, but how would i go about implementing this?
njw — Mon Sep 25, 2006 9:23 am
Steve has written a tutorial here http://framework.weblite.ca/documentation/tutorial/getting_started/permissions
Neil
compudude86 — Mon Sep 25, 2006 9:35 am
aahaa! thank you very much for pointing that out!!
njw — Mon Sep 25, 2006 10:42 am
No problem
compudude86 — Tue Oct 17, 2006 11:13 am
ok, i set it up, any idea how i would be able to “jail” a user to a certain table by username? lets spread this out:
i have 3 users, and tables A-C:
user 3 may view and edit table A, but not b and c, user 2 may only control table b, but not a or c, and user 3 can only read table c, and cannot even see a-b. is that type of thing possible in the authentication systems?
shannah — Tue Oct 17, 2006 4:55 pm
Okay.. there are two issues to consider here.
- Security - making sure that users cannot use the tables/records/fields that you don’t want them to.
- Usability - making the applications flow work properly for the user at hand.
On the security side of things, it is easy to “jail” a user. Simply define the getPermissions() methods on the three tables in such a way that the appropriate permissions are returned for each user. In your example above you would define the getPermissions() method for the A table as:
- Code: Select all
function getPermissions(&$record){ $auth =& Dataface_AuthenticationTool::getInstance(); $user =& $auth->getLoggedInUser(); // $user is a Dataface_Record encapsulating the currently logged in user. // first let's deal with the case that the user is not logged in. if ( !$user ) return Dataface_PermissionsTool::NO_ACCESS(); if ( $user->val('userid') == 3 ) return Dataface_PermissionsTool::ALL(); // If i understand the specs correctly, then user 3 is the only one that can access table 'A' at all // so we revoke access to everyone else. return Dataface_PermissionsTool::NO_ACCESS(); }
You would do similar things for the other tables to make sure that only authorized users can access them.
On the usability side, there are a number of things that you can do to tailor the application to your needs here.
The permissions will help a lot, but you may end up with a situation where users see “Permission denied” alot. This is where you have to tell your application to be “smart”.
This is a fairly big topic that deserves a lot of space and discussion, but I’ll begin by listing some of the more common hurdles:
- The table tabs at the top of the app show up the same for each user - what if you want some tables to be hidden for some users.
- If no table is specified in the URL, then the user is always directed to the first table in the tables menu. What if you want this to depend on which user is logged in?
- The default action is ‘list’. What if you want this to be different?
- Some parts of the application may be confusing to some users, and are better hidden (e.g. how to hide the search box).
There may be more issues but their solutions will be similar.
Solutions:
- The table tabs, for performance reasons, are just statically generated.. they don’t take into account any permissions. Of course if a user clicks on a table that he has no access to he’ll receive a permission-denied error. So how do we get around this.
a. You could remove these tabs altogether. You can do this by defining a getPreferences() method in the Application’s delegate class. This will return an associative array of preferences. see http://framework.weblite.ca/documentation/manual/delegate_classes for more on this.
b. You could override this slot with your own tabs using the ‘table_tabs’ slot in the Application’s delegate class.
e.g:
- Code: Select all
- `function block__table_tabs(){
$auth =& Dataface_AuthenticationTool::getInstance();
$user =& $auth->getLoggedInUser();
// … now display table tabs depending on who is logged in.}`
.. more later.. i’m out of time for now….
Please let me know if there are particular aspects that you are more interested in so that I can target the response..
best regards
Steve
compudude86 — Fri Nov 10, 2006 12:26 pm
ok, i think i just made it more complicated…….
for example……
john doe works for company A, so when he uses his username or password, i want him to only get into (databaseIST table:COMPANY-A), and nothing more. only his username, only that database and table. now, jane doe, works for company B. therefore, she can only access (databaseIST table:COMPANY-B), not company A. then, you have john smith, hes not a distributor, so hes not allowed anywhere near (databaseIST), hes only allowed in (database:BOOK tableRODUCTS) and he is not allowed editing rights(which i think ive got that figured out so far with the read only/admin priveledges set up) i dont know if it makes any sense, basically i need to access two different database sets, with different permissions, from the same “application”
shannah — Fri Nov 10, 2006 5:54 pm
Dataface applications are made to interact with only a single database - but it may be possible to work around this “limitation” for your purposes.
A little-used feature of the df_init() method is that it can take an optional third parameter - an associative array of options that are used as the conf.ini options. This will allow you to theoretically connect to multiple databases (you would choose which database you need to connect to at the beginning of your application’s index.php file.
For example:
- Code: Select all
- `php<br /require_once ‘/path.to.dataface/dataface-public-api.php’;
$conf = parse_ini_file(‘conf.ini’, true);
if ( $_REQUEST[‘-db’] == ‘BOOK’ ) $conf[‘_database’][‘name’] = ‘BOOK’;
else $conf[‘_database’][‘name’] = ‘OTHERDB’;df_init(FILE, ‘/url.to.dataface’, $conf);
$app =& Dataface_Application::getInstance();
$app->display();?>`
Then from anywhere in your application (e.g. your triggers, etc..) you can always find out which database you are using by:
- Code: Select all
$app =& Dataface_Application::getInstance(); $db_name = $app->_conf['_database']['name'];
An alternative strategy (which is probably better) is just to have separate dataface applications for each database. If there are common elements between the databases you can use symbolic links to share common configuration files, etc..
One bit of curiosity, is why use multiple dbs? Why not just use one db?
Hope this helps a little.
-Steve
compudude86 — Sun Nov 19, 2006 6:35 am
i see. two reasons for the multiple databases, 1. the distributors cant look at the other distributors products, as its in contracts that their pricing cant be viewed by the other distributors, and 2 because we will be taking the distributors databases and appending them to the main database after we verify them. theres something like 7-9 distributors, each must have their own table, which can only be pulled up by the right user. basically, i want to define the proper DB, table, and permissions by the username.
Aoirthoir — Sun Nov 19, 2006 8:46 pm
I’m personally using multiple databases to keep information organized by type. All customer tables in one DB, all vendor tables in another etc. Also since I am using VMware Server Edition, and currently running an Ubuntu LAMP within that, Ive got soft links from /var/lib/mysql/tablename to /media/somevirtualdrive which allows me to keep all of my related tables on its own virtual drive..so a back up is real easy. Ive got to keep the DBs seperated in that case to insure they remain 4gig or less each. A bit of work..but in the long run its saved me lots and lots of time with restores.
compudude86 — Mon Nov 20, 2006 11:35 am
i see. so is there a way to assign a database:table by user? so lets say user a logs in, the app knows that user A is supposed to get user:book but user B is supposed to get dist:companyB ? if that makes sense
shannah — Mon Nov 20, 2006 3:53 pm
yes this is possible.. but it will require at least a little PHP, depending on which way you do it.
Is it possible to have different users access it at different subdomains? E.g. users from companyB log in using
companyB.yourdomain.com
and users from company A log in using
companyA.yourdomain.com
That way you can easily extract which database you want to use via the $_SERVER[‘HTTP_HOST’] variable.
Then, altering the example from the above post:
- Code: Select all
- `php<br /require_once ‘/path.to.dataface/dataface-public-api.php’;
$conf = parse_ini_file(‘conf.ini’, true);list($company) = explode(‘.’, $_SERVER[‘HTTP_HOST’]);
// extracts the first part of the domain from the request.
// e.g. if the domain was companyA.yourdomain.com, then $company
// would now contain the string ‘companyA’$conf[‘_database’][‘name’] = $company;
// Let’s assume here that all of our databases are named after companies
// e.g. databases: companyA, companyB, companyC, etc…
// Then this will set the database’s name to that companydf_init(FILE, ‘/url.to.dataface’, $conf);
$app =& Dataface_Application::getInstance();
$app->display();?>`
Hopefully this helps you a little with the idea.
-Steve
njw — Tue Nov 21, 2006 3:29 am
Could you do this from a User table? Perhaps always connect initially to the first database, go through login, get the correct database from the user table row and then switch if necessary.
I am still a bit at a loss as to why you need more than one database though, as you should be able to put all the tables into one database and then use permissions to allow users to access individual tables. It would make management of the data simpler!
shannah — Tue Nov 21, 2006 2:12 pm
Yes.. this is a clever idea.
I suppose that at any point of your application, you could make a call to mysql_select_db() and switch databases.
Clever .. very clever…
-Steve
Aoirthoir — Tue Nov 21, 2006 5:21 pm
Then this is something I definitely want to explore. It would make things a lot easier. Even from the point of view of an app…say one DB for my vendors, the other for the patients and so on as mentioned. Then list those in the original DB…
So the initial path.to.dataface.app/index.php could simply be an entry way to multiple DF apps.
Also….a while ago you were working on storing the df settings in a DB instead of in ini files. And if I understand correctly..the ini settings are in variables..so couldnt we make our own calls to a DB and replace those values ourselves?
Thanks.
compudude86 — Mon Nov 20, 2006 11:35 am
i see. so is there a way to assign a database:table by user? so lets say user a logs in, the app knows that user A is supposed to get user:book but user B is supposed to get dist:companyB ? if that makes sense
shannah — Mon Nov 20, 2006 3:53 pm
yes this is possible.. but it will require at least a little PHP, depending on which way you do it.
Is it possible to have different users access it at different subdomains? E.g. users from companyB log in using
companyB.yourdomain.com
and users from company A log in using
companyA.yourdomain.com
That way you can easily extract which database you want to use via the $_SERVER[‘HTTP_HOST’] variable.
Then, altering the example from the above post:
- Code: Select all
- `php<br /require_once ‘/path.to.dataface/dataface-public-api.php’;
$conf = parse_ini_file(‘conf.ini’, true);list($company) = explode(‘.’, $_SERVER[‘HTTP_HOST’]);
// extracts the first part of the domain from the request.
// e.g. if the domain was companyA.yourdomain.com, then $company
// would now contain the string ‘companyA’$conf[‘_database’][‘name’] = $company;
// Let’s assume here that all of our databases are named after companies
// e.g. databases: companyA, companyB, companyC, etc…
// Then this will set the database’s name to that companydf_init(FILE, ‘/url.to.dataface’, $conf);
$app =& Dataface_Application::getInstance();
$app->display();?>`
Hopefully this helps you a little with the idea.
-Steve
njw — Tue Nov 21, 2006 3:29 am
Could you do this from a User table? Perhaps always connect initially to the first database, go through login, get the correct database from the user table row and then switch if necessary.
I am still a bit at a loss as to why you need more than one database though, as you should be able to put all the tables into one database and then use permissions to allow users to access individual tables. It would make management of the data simpler!
shannah — Tue Nov 21, 2006 2:12 pm
Yes.. this is a clever idea.
I suppose that at any point of your application, you could make a call to mysql_select_db() and switch databases.
Clever .. very clever…
-Steve
Aoirthoir — Tue Nov 21, 2006 5:21 pm
Then this is something I definitely want to explore. It would make things a lot easier. Even from the point of view of an app…say one DB for my vendors, the other for the patients and so on as mentioned. Then list those in the original DB…
So the initial path.to.dataface.app/index.php could simply be an entry way to multiple DF apps.
Also….a while ago you were working on storing the df settings in a DB instead of in ini files. And if I understand correctly..the ini settings are in variables..so couldnt we make our own calls to a DB and replace those values ourselves?
Thanks.
shannah — Tue Nov 21, 2006 6:08 pm
Yes you are always able to make your own calls to whatever DB you want. The solution of switching dbs on the current database connection (suggested by Neil) would allow us to effectively change which database Dataface uses for all of its stuff.
compudude86 — Wed Nov 22, 2006 11:51 am
i dont want to do the subdomain thing as its way too much trouble, mostly for the users who are 40-somethings who just learned about the computer not too long ago. the way i see it is the app would simply “know” by the login name, what database and table they should be locked in. most likely by adding a field to the users database with what database and table they should be in, unless the app is locked to one database, im not sure.
compudude86 — Wed Nov 22, 2006 11:56 am
sorry, i shouldve clarified, by users database i mean the one that stores the usernames and passwords. i was also thinking if there is a way to use the user management that mysql offers that might work too
shannah — Wed Nov 22, 2006 12:24 pm
First.. this is very possible and not difficult for an PHP programmer to develop in under a couple of hours. However it is difficult for me to give you a full “how-to” here because the implementation will depend on a lot of factors such as:
- Are all of the databases identical in schema, with just different data stored?
- Is it possible that a user may need to use both databases?
My inclination (still dependent upon the answers to the above questions) would be to have separate applications for each database. Then develop a custom login page that takes the username and password and forwards them to the correct application upon login.
If you would like a hand with this project or would like anything implemented, please feel free to contact me about my consulting services.
Best regards
Steve
yusif — Wed Feb 07, 2007 11:59 am
Hi Steve,
This might be an old issue, but I just got into this problem. I really need a solution to the second case you specified i.e.
I want for different users, different tables to show first. Basically, I do not have the tabs in my setup. I use a link to access the tables. If a user logs in he should have access to the table meant for him to access not necessarily the first table in the conf.ini
Hope to here from you soon.
Regards
Yusif
Okay.. there are two issues to consider here.
- Security - making sure that users cannot use the tables/records/fields that you don’t want them to.
shannah — Wed Feb 07, 2007 1:34 pm
Hi Yusif,
You can specify which table is to be accessed by altering the query.Ê Do this in your index.php file sometime before you call $app->display()
eg.
if ( !isset($_REQUEST[‘-table’]) ){
ÊÊÊ // Find out which table should be first based on who is logged in.. then set the value:
Ê Ê $query =& $app->getQuery();
Ê Ê $query[‘-table’] = ‘mytable’;
}
Something like that should work.
-SteveÊ
yusif — Wed Feb 07, 2007 2:51 pm
Hi Steve,
I tried that but had this error
Fatal error: Undefined class name ‘dataface_authenticationtool’ in C:\Program Files\Apache Group\Apache2\htdocs\uwg\ePledge.php on line 8
my index.php looks like this
getLoggedInUser();
$rightTable = $user->val(‘Base’);
$query =& $app->getQuery();
$query[‘-table’] = $rightTable;
}
$app->display();
?>
“Base” is a field in my users table which stores the table allowed to be viewed by the user.
-Yusif
shannah — Thu Feb 08, 2007 4:40 am
Evidently at that point in your app, the authentication tool class hasn’t been loaded yet. So you can load it:
import(‘Dataface/AuthenticationTool.php’);
shannah — Thu Feb 08, 2007 11:03 am
Sorry.. this way won’t work I realize because the user doesn’t get authenticated until the call to $app->display().
Hence you have to put your code inside a method that will get called after authentication.
Here is what you need to do. Inside the getPreferences() method of the application delegate class, you can do your tests:
- Code: Select all
- `function getPreferences(){
$auth =& Dataface_AuthenticationTool::getInstance();
$user =& $auth->getLoggedInUser();
if ( $user ){
$rightTable = $user->val(‘Base’);
$app =& Dataface_Application::getInstance();
$query =& $app->getQuery();
if ( $query[‘-table’] != $rightTable ){
header(‘Location: ‘.$app->url(‘-table=’.$rightTable));
exit;}
}
return array();
}`
efren.serrano — Fri Apr 09, 2010 1:25 am
Hi Steven,
Thanks for share Xataface, is a great system to manage database.
I’m a newbbie learning how to build a multiuser system with xataface.
I was reading a lot of posts and learning with the wiki and samples in the web, but, in this point i don’t know what is the better form to make that i want.
My case is this:
i have 4 roles with x users.
if my user don’t have permissions to see the first table of the conf.ini file, i show one restricted notification “Permission to perform action ‘list’ denied” but i want to redirect and load the menu for this user, to access to all the tables that he can see.
If use the getPreferences method, only can see the ‘Base’ table.
¿What it’s the better method to make this?
Thanks in advance
shannah — Wed Feb 07, 2007 1:34 pm
Hi Yusif,
You can specify which table is to be accessed by altering the query.Ê Do this in your index.php file sometime before you call $app->display()
eg.
if ( !isset($_REQUEST[‘-table’]) ){
ÊÊÊ // Find out which table should be first based on who is logged in.. then set the value:
Ê Ê $query =& $app->getQuery();
Ê Ê $query[‘-table’] = ‘mytable’;
}
Something like that should work.
-SteveÊ
yusif — Wed Feb 07, 2007 2:51 pm
Hi Steve,
I tried that but had this error
Fatal error: Undefined class name ‘dataface_authenticationtool’ in C:\Program Files\Apache Group\Apache2\htdocs\uwg\ePledge.php on line 8
my index.php looks like this
getLoggedInUser();
$rightTable = $user->val(‘Base’);
$query =& $app->getQuery();
$query[‘-table’] = $rightTable;
}
$app->display();
?>
“Base” is a field in my users table which stores the table allowed to be viewed by the user.
-Yusif
shannah — Thu Feb 08, 2007 4:40 am
Evidently at that point in your app, the authentication tool class hasn’t been loaded yet. So you can load it:
import(‘Dataface/AuthenticationTool.php’);
shannah — Thu Feb 08, 2007 11:03 am
Sorry.. this way won’t work I realize because the user doesn’t get authenticated until the call to $app->display().
Hence you have to put your code inside a method that will get called after authentication.
Here is what you need to do. Inside the getPreferences() method of the application delegate class, you can do your tests:
- Code: Select all
- `function getPreferences(){
$auth =& Dataface_AuthenticationTool::getInstance();
$user =& $auth->getLoggedInUser();
if ( $user ){
$rightTable = $user->val(‘Base’);
$app =& Dataface_Application::getInstance();
$query =& $app->getQuery();
if ( $query[‘-table’] != $rightTable ){
header(‘Location: ‘.$app->url(‘-table=’.$rightTable));
exit;}
}
return array();
}`
efren.serrano — Fri Apr 09, 2010 1:25 am
Hi Steven,
Thanks for share Xataface, is a great system to manage database.
I’m a newbbie learning how to build a multiuser system with xataface.
I was reading a lot of posts and learning with the wiki and samples in the web, but, in this point i don’t know what is the better form to make that i want.
My case is this:
i have 4 roles with x users.
if my user don’t have permissions to see the first table of the conf.ini file, i show one restricted notification “Permission to perform action ‘list’ denied” but i want to redirect and load the menu for this user, to access to all the tables that he can see.
If use the getPreferences method, only can see the ‘Base’ table.
¿What it’s the better method to make this?
Thanks in advance
shannah — Fri Apr 09, 2010 6:48 am
Probably the best way to handle this would be to create a dashboard by way of making a common first table that everyone can see. There is a how-to in the wiki specifically showing how to do this.
You can override the table tabs with your own options using blocks and slots.
For permissions, don’t need to do anything fancy. Just implement your getPermissions() methods (first in the application delegate class) to restrict access according to
your business rules.