first of all I want to thank you for your great work. I had tried to put up some MySQL gui before - but due to my limited time never came to the point where I trusted my code enough to use it for a live system
Dear Xataface community,
up till now a have read a lot in this forum but never been active myself. Since everyone using a system like Xataface has different needs I now want to share my experience on the topic stated above since that was one of my primary concerns.
After realizing the power of Xataface I was facing the problem that I had many related tables with some of them containing sensible data not to be exposed to the public. After reading about Xataface permissions I found that the mechanism provided by conf.ini with [_tables], [_disallowed_tables] and [_allowed_tables] would be the top level/most secure one. But this mechanism seemed to be static. Working with the Xataface 1.3.2 code I found the following solution to my needs especially providing a consistant Xataface gui by using conf/ApplicationDelegate.php class:
- Code: Select all
class conf_ApplicationDelegate {
function disable_table($table) {
$app =& Dataface_Application::getInstance(); unset($app->_conf['_allowed_tables'][$table]); }
function enable_table($table, $name) {
$app =& Dataface_Application::getInstance(); $app->_conf['_allowed_tables'][$table] = $table; }
function hide_table($table) {
$app =& Dataface_Application::getInstance(); unset($app->_conf['_tables'][$table]); unset($app->_conf['_allowed_tables'][$table]); }
function show_table($table, $name) {
$app =& Dataface_Application::getInstance(); $app->_conf['_tables'][$table] = $name; $app->_conf['_allowed_tables'][$table] = $table; }
function beforeHandleRequest() {
$app =& Dataface_Application::getInstance();
$query =& $app->getQuery();
if($query['-table'] == 'Dashboard' and $query['-action'] == 'list') $query['-action'] = 'dashboard';
$auth =& Dataface_AuthenticationTool::getInstance();
$user =& $auth->getLoggedInUser();
if(isset($user)) {
switch($user->val('user')) {
case 'userX':
$this->show_table('tbl_everyone', 'Table seen by everyone';
$this->show_table('tbl_userx', 'Table seen/accessable only by userX');
break;
default:
$this->show_table('tbl_everyone', 'Table seen by everyone';
}
}
}
}
together with listing all my tables under [_disallowed_tables] in the conf.ini and only my Dashboard under [_tables]. The fine grained access control on the exposed tables is done by Xatafaces permission system using table delegate classes.
=> This solution works really flawless with Xataface 1.3.2.
After my system grew in the past months I noticed an annoying problem. Using MySQL views to filter data - meaning the views are not complex representing one single table and for this reason are still writeable - creating new records behaves bad. After entering the record data a click to the save button leeds to an empty result set with the message: record created/saved successfully. no record matching criteria found. If I click on the find action I notice that the auto_increment value of the primary key is in this case not handled correctly. The find form indicates for the ID field just = meaning the new ID is not passed to xataface at all. This happens in all combinations fields.ini key=PRI together with widget:type=static/hidden/... . The same setup working on the original table not the view works flawlessly. Since I was not finding any information about this issue I wanted to try Xataface SVN since I thouhgt, maybe this problem is already solved there. So I setup xataface_svn together with the svn g2 module.
=> Surprise! This solution is not working with the new Xataface SVN!!!
=> Further reading and trying to unserstand the code even more brouhgt me to this other solution which seems to be the more intended way.
=> But this new solution needs a minor patch of the XatafaceSVN code.
Looking at Dataface/Application.php shows that there ist another delegate function called conf(). Seems to be the right place for the things I did in first place. So I changed my conf/ApplicationDelegate.php:
- Code: Select all
class conf_ApplicationDelegate {
var $_conf;
function disable_table($table) {
unset($this->_conf['_allowed_tables'][$table]); }
function enable_table($table, $name) {
$this->_conf['_allowed_tables'][$table] = $table; }
function hide_table($table) {
unset($this->_conf['_tables'][$table]); unset($this->_conf['_allowed_tables'][$table]); }
function show_table($table, $name) {
$this->_conf['_tables'][$table] = $name; $this->_conf['_allowed_tables'][$table] = $table; }
function conf() {
$this->_conf = array();
$auth =& Dataface_AuthenticationTool::getInstance();
$user =& $auth->getLoggedInUser();
if(isset($user)) {
switch($user->val('user')) {
case 'userX':
$this->show_table('tbl_everyone', 'Table seen by everyone';
$this->show_table('tbl_userx', 'Table seen/accessable only by userX');
break;
default:
$this->show_table('tbl_everyone', 'Table seen by everyone';
}
}
return $this->_conf;
}
function beforeHandleRequest() {
$app =& Dataface_Application::getInstance();
$query =& $app->getQuery();
if($query['-table'] == 'Dashboard' and $query['-action'] == 'list') $query['-action'] = 'dashboard';
}
}
This worked in conjunction with the g2 module but at all places except the upper navigation menu instead of the table names the table ids like tbl_... got used. Disabling the g2 module made the menu disappear in the old layout. A little debugging showed me that Xataface ist using _table, _conf['_table'] and con() a little bit unconsistantly. (at least to my pure understanding of Xataface code) The desired result ist finally consisntantly achieved by patching the original Dataface/Application.php: function display() in the following way:
!PATCH!
- Code: Select all
function display($main_content_only=false, $disableCache=false){
// ---------------- Set the Default Character set for output -----------
//!PATCH! comment out the following three lines and copy them to the new location
//foreach ($this->_tables as $key=>$value){
// $this->_tables[$key] = $this->_conf['_tables'][$key] = df_translate('tables.'.$key.'.label', $value);
//}
$this->main_content_only = $main_content_only;
if ( $this->autoSession or $this->sessionEnabled() ){
$this->startSession();
}
//... (other code cut out)
// handle authentication
if ( !(defined('XATAFACE_DISABLE_AUTH') and XATAFACE_DISABLE_AUTH) and isset($this->_conf['_auth']) ){
//...
if ( PEAR::isError($auth_result) and $auth_result->getCode() == DATAFACE_E_LOGIN_FAILURE ){
// There was a login failure, show the login prompt
$loginPrompt = true;
$loginError = $auth_result->getMessage();
} else if ( $authTool->isLoggedIn() ){
// The user is logged in ok
// Handle the request
//!PATCH! insert the three lines here with modified first row!
foreach ($this->conf()['_tables'] as $key=>$value){
$this->_tables[$key] = $this->_conf['_tables'][$key] = df_translate('tables.'.$key.'.label', $value);
}
$result = $this->handleRequest();
if ( Dataface_Error::isPermissionDenied($result) ){
// Permission was denied on the request. Since the user is already
// logged in, there is no use giving him the login prompt. Just give
// him the permission denied screen.
$permissionDenied = true;
$permissionError = $result->getMessage();
}
//...
Note: The same minor patch is possible with Xataface 1.3.2 making the same conf/ApplicationDelegate.php work with both versions in a consistent/expected way.
During my investigations I found another small problem introduced by the priority of the overwriting of smarty template code in conjunction with the new g2 module theme.
=> Solution: minor patch to Dataface/SkinTool.php
- Code: Select all
function register_skin( $name, $template_dir){
if ( !is_array($this->template_dir) ){
if ( strlen($this->template_dir) > 0 ){
$this->template_dir = array($this->template_dir);
} else {
$this->template_dir = array();
}
}
//!PATCH! added next line
if(count($this->template_dir) >= 3) $slt = array_shift($this->template_dir);
array_unshift($this->template_dir, $template_dir);
//!PATCH! added next line
if(isset($slt)) array_unshift($this->template_dir, $slt);
$this->skins[$template_dir] = $name;
}
preserving the SITE/templates having highest priority at all time.
I hope that this might be useful to someone.
Sincerely yours
Torben
P.S.: Finally I'd like to ask one question by myself:
I noticed that the new g2 look&feel seems to be missing some features. E.g. in the result list I find no pages links and cannot adapt the number of elements per page. Is this functionality in the g2 still missing or do I have to update some settings (permissions.ini, conf.ini / [_prefs]) ?
P.P.S: If someone has an idea how to make inserting records into views work I would be really interested since this was my original intention playing with the xataface code;-)