Changed access control extensions support for modules/plugins to use unique extension...
authorJanusz Dobrowolski <janusz@frontaccounting.eu>
Sat, 10 Oct 2009 12:29:22 +0000 (12:29 +0000)
committerJanusz Dobrowolski <janusz@frontaccounting.eu>
Sat, 10 Oct 2009 12:29:22 +0000 (12:29 +0000)
admin/db/maintenance_db.inc
admin/security_roles.php
includes/access_levels.inc
includes/current_user.inc
index.php
installed_extensions.php

index 5984094f864c7c66e999d8d7a1888e9eb1208cf7..f018ea1dda67586bd5b88b330d5694772de102ee 100644 (file)
@@ -21,7 +21,7 @@
 function array_natsort($aryData, $strIndex, $strSortBy, $strSortType=false)
 {
    //    if the parameters are invalid
-   if (!is_array($aryData) || !$strIndex || !$strSortBy)
+   if (!is_array($aryData) || !$strSortBy)
        //    return the array
        return $aryData;
 
@@ -29,9 +29,9 @@ function array_natsort($aryData, $strIndex, $strSortBy, $strSortType=false)
    $arySort = $aryResult = array();
 
    //    loop through the array
-   foreach ($aryData as $aryRow)
+   foreach ($aryData as $key => $aryRow)
        //    set up the value in the array
-       $arySort[$aryRow[$strIndex]] = $aryRow[$strSortBy];
+       $arySort[$strIndex ? $aryRow[$strIndex] : $key] = $aryRow[$strSortBy];
 
    //    apply the natural sort
    natsort($arySort);
@@ -42,13 +42,16 @@ function array_natsort($aryData, $strIndex, $strSortBy, $strSortType=false)
        arsort($arySort);
 
    //    loop through the sorted and original data
-   foreach ($arySort as $arySortKey => $arySorted)
-       foreach ($aryData as $aryOriginal)
-           //    if the key matches
-           if ($aryOriginal[$strIndex]==$arySortKey)
-               //    add it to the output array
-               array_push($aryResult, $aryOriginal);
-
+               foreach ($arySort as $arySortKey => $arySorted)
+                       if($strIndex) 
+                       {
+                               foreach ($aryData as $aryOriginal)
+                               // if the key matches
+                                       if ($aryOriginal[$strIndex]==$arySortKey)
+                                               // add it to the output array
+                                               array_push($aryResult, $aryOriginal);
+                       } else
+                               $aryResult[$arySortKey] = $aryData[$arySortKey];
    //    return the return
    return $aryResult;
 }
@@ -120,24 +123,23 @@ function write_config_db($new = false)
        return 0;
 }
 
-function write_extensions($extensions=null, $company = null)
+function write_extensions($extensions=null, $company = -1)
 {
-       global $path_to_root, $installed_extensions;
+       global $path_to_root, $installed_extensions, $next_extension_id;
 
        if (!isset($extensions)) {
                $extensions = $installed_extensions;
        }
-       
-       $exts = array_natsort($extensions, 'name', 'name');
-       $extensions = $exts;
 
-       $n = count($exts);
+//     $exts = array_natsort($extensions, 'name', 'name');
+//     $extensions = $exts;
 
        $msg = "<?php\n\n";
        if ($company == -1)
                $msg .=
-"/* List of installed additional modules and plugins. If adding extensions at the beginning 
-       of the list, make sure it's index is set to 0 (it has ' 0 => ');
+"/* List of installed additional modules and plugins. If adding extensions manually 
+       to the list make sure they have unique, so far not used extension_ids as a keys,
+       and \$next_extension_id is also updated.
        
        'name' - name for identification purposes;
        'type' - type of extension: 'module' or 'plugin'
@@ -147,8 +149,10 @@ function write_extensions($extensions=null, $company = null)
        'title' - is the menu text (for plugin) or new tab name
        'active' - current status of extension
        'acc_file' - (optional) file name with \$security_areas/\$security_sections extensions; 
-               related to 'path'.
-*/\n\n";
+               related to 'path'
+       'access' - security area code in string form
+*/
+\n\$next_extension_id = $next_extension_id; // unique id for next installed extension\n\n";
        else 
                $msg .=
 "/*
@@ -157,15 +161,12 @@ function write_extensions($extensions=null, $company = null)
 */\n\n";
 
        $msg .= "\$installed_extensions = array (\n";
-       if ($n > 0)
-           $msg .= "\t0 => ";
-       for ($i = 0; $i < $n; $i++)
+       foreach($extensions as $i => $ext) 
        {
-               if ($i > 0)
-                       $msg .= "\t\t";
+               $msg .= "\t$i => ";
                $msg .= "array ( ";
                $t = '';
-               foreach($extensions[$i] as $key => $val) {
+               foreach($ext as $key => $val) {
                        $msg .= $t."'$key' => '$val',\n";
                        $t = "\t\t\t";
                }
@@ -173,7 +174,7 @@ function write_extensions($extensions=null, $company = null)
        }
        $msg .= "\t);\n?>";
 
-       $filename = $path_to_root . (isset($company) ? '/company/'.$company : '')
+       $filename = $path_to_root . ($company==-1 ? '' : '/company/'.$company)
                .'/installed_extensions.php';
 
        // Check if the file is writable first.
index 5617eb79a9ede3b45bfe730bfa74e561f0c0bd9f..ef7e23ed0580217207c492221099be86ea8eee1f 100644 (file)
@@ -22,6 +22,17 @@ include_once($path_to_root . "/includes/access_levels.inc");
 include_once($path_to_root . "/admin/db/security_db.inc");
 
 $new_role = get_post('role')=='' || get_post('cancel') || get_post('clone'); 
+//--------------------------------------------------------------------------------------------------
+// Following compare function is used for sorting areas 
+// in such a way that security areas defined by module/plugin
+// is properly placed under related section regardless of 
+// unique extension number
+//
+function comp_areas($area1, $area2) 
+{
+       return ($area1[0]&0xffff)-($area2[0]&0xffff);
+}
+
 //--------------------------------------------------------------------------------------------------
 if (list_updated('role')) {
        $Ajax->activate('details');
@@ -64,14 +75,20 @@ if (get_post('addupdate'))
                $sections = array();
                $areas = array();
                foreach($_POST as $p =>$val) {
-                       if (substr($p,0,4) == 'Area')
-                               $areas[] = substr($p, 4);
+                       if (substr($p,0,4) == 'Area') {
+                               $a = substr($p, 4);
+                               if (($a&~0xffff) && (($a&0xff00)<(99<<8))) {
+                                       $sections[] = $a&~0xff; // add extended section for plugins
+                               }
+                               $areas[] = $a;
+                       }
                        if (substr($p,0,7) == 'Section')
                                $sections[] = substr($p, 7);
                }
-               
-               sort($areas);
-               sort($sections);
+               uasort($areas, 'comp_areas');
+
+               $sections = array_values($sections);
+               _vd($sections);
        if ($new_role) 
                {
                        add_security_role($_POST['name'], $_POST['description'], $sections, $areas); 
@@ -114,7 +131,7 @@ if (get_post('cancel'))
 if (!isset($_POST['role']) || get_post('clone') || list_updated('role')) {
        $id = get_post('role');
        $clone = get_post('clone');
-//     clear_data();
+
        unset($_POST);
        if ($id) {
                $row = get_security_role($id);
@@ -161,7 +178,6 @@ if (get_post('_show_inactive_update')) {
 }
 if (find_submit('_Section')) {
        $Ajax->activate('details');
-//     set_focus('');
 }
 //-----------------------------------------------------------------------------------------------
 div_start('details');
@@ -174,16 +190,22 @@ end_table(1);
        start_table("$table_style width=40%");
 
        $k = $j = 0; //row colour counter
-       $m = 0;
-       asort($security_areas); // in the case installed external modules has added some lines
+       $ext = $sec = $m = -1;
+       uasort($security_areas,'comp_areas');
        foreach($security_areas as $area =>$parms ) {
                // system setup areas are accessable only for site admins i.e. 
                // admins of first registered company
-               if (user_company() && (($parms[0]&~0xff) == SS_SADMIN)) continue;
-
-               if (($parms[0]&~0xff) != $m)
+               if (user_company() && (($parms[0]&0xff00) == SS_SADMIN)) continue;
+               
+               $newsec = ($parms[0]>>8)&0xff;
+               $newext  = $parms[0]>>16;
+               if ($newsec != $sec || (($newext != $ext) && ($newsec>99)))
                { // features set selection
+                       $ext = $newext; 
+                       $sec = $newsec;
                        $m = $parms[0] & ~0xff;
+//                     if(!isset($security_sections[$m]))
+//                      display_error(sprintf("Bad section %X:", $m));
                        label_row($security_sections[$m].':', 
                                checkbox( null, 'Section'.$m, null, true, 
                                        _("On/off set of features")),
index b35890bd7df3e1ffcea909e773036d680309a5f5..4a43331af7f09de0cf253ffeddff98354890fcca 100644 (file)
        Every security section can contain up to 256 different areas.
        External modules can extend security roles system by adding rows to 
        $security_sections and $security_areas using section codes >=100.
+       Security areas and sections created by extension modules/plugins
+       have dynamically assigned 3-byte integer codes. The highest byte is zero
+       for sections/areas defined in this file, and extid+1 for those defined 
+       by extensions 
 */
 define('SS_SADMIN',    1<<8);  // site admin
 define('SS_SETUP',     2<<8);  // company level setup
@@ -245,15 +249,57 @@ $security_areas =array(
        . on any page with non-standard security areas
        . in security roles editor
        The call should be placed between session.inc inclusion and page() call.
+       Up to 155 security sections and 155 security areas for any extension can be installed.
 */
 function add_access_extensions()
 {
-       global $path_to_root, $security_areas, $security_sections, $installed_extensions;
+       global $security_areas, $security_sections, $installed_extensions;
 
-       foreach($installed_extensions as $ext) {
-               if (@$ext['active'] && isset($ext['acc_file']))
-                       include($path_to_root.($ext['type'] == 'plugin' ? '/modules/':'/').$ext['path'].'/'.$ext['acc_file']);
+       foreach($installed_extensions as $extid => $ext) {
+               $scode = 100;
+               $acode = 100;
+               $accext = get_access_extensions($extid);
+               $extsections = $accext[1];
+               $extareas = $accext[0];
+               $extcode = $extid<<16;
+               
+               $trans = array();
+               foreach($extsections as $code =>$name) {
+                       $trans[$code] = $scode<<8;
+                       // reassign section codes
+                       $security_sections[$trans[$code]|$extcode] = $name;
+                       $scode++;
+               }
+               foreach($extareas as $code => $area) {
+                       $section = $area[0]&0xff00;
+                       // extension modules:
+                       // if area belongs to nonstandard section
+                       // use translated section codes and
+                       // preserve lower part of area code
+                       if (isset($trans[$section])) {
+                               $section = $trans[$section];
+                       } 
+                               // otherwise assign next available
+                               // area code >99
+                       $area[0] = $extcode | $section | ($acode++);
+                       $security_areas[$code] = $area;
+               }
        }
 }
+/*
+       Helper function to retrieve extension access definitions in isolated environment.
+*/
+function get_access_extensions($id) {
+       global $path_to_root, $installed_extensions;
+       
+       $ext = $installed_extensions[$id];
+       
+       $security_sections = $security_areas = array();
+       
+       if (isset($ext['acc_file']))
+               include($path_to_root.($ext['type'] == 'plugin' ? '/modules/':'/').$ext['path'].'/'.$ext['acc_file']);
+
+       return array($security_areas, $security_sections);
+}
 
 ?>
\ No newline at end of file
index bb265047d0934bf6637318106c40a6986f194762..5aa5e641e58fdf2557dddcdcebf05e5e022e5916 100644 (file)
@@ -127,7 +127,6 @@ class current_user
        function can_access($page_level)
        {
                global $security_groups, $security_areas;
-
                if (isset($security_groups)) {
                        return $this->company == 0 &&
                                in_array(20, $security_groups[$this->access]);
@@ -135,7 +134,7 @@ class current_user
 
                if ($page_level === 'SA_OPEN') 
                        return true;
-               $code = @$security_areas[$page_level][0];
+               $code = $security_areas[$page_level][0];
 
                // only first registered company has site admin privileges
                return $code && in_array($code, $this->role_set)
@@ -147,11 +146,11 @@ class current_user
                return $this->can_access($page_level);
        }
 
-       function get_db_connection()
+       function get_db_connection($id=-1)
        {
        global $db_connections;
 
-       $connection = $db_connections[$this->company];
+       $connection = $db_connections[$id == -1 ? $this->company : $id];
 
        //print_r($connection);
 
index aa0e763e3eefa9bdd4ad24a758997c1e8a1715ca..ab6764f0204a0dcb10a26091027f3c7ce6085b45 100644 (file)
--- a/index.php
+++ b/index.php
@@ -14,6 +14,7 @@
        ini_set('xdebug.auto_trace',1);
        include_once("includes/session.inc");
 
+       add_access_extensions();
        $app = &$_SESSION["App"];
        if (isset($_GET['application']))
                $app->selected_application = $_GET['application'];
index b83e3cfb66645e973b1efb44032aee80ef03e122..8afb638b908c9a63899fe628a634f3b8400cb9af 100644 (file)
@@ -1,7 +1,8 @@
 <?php
 
-/* List of installed additional modules and plugins. If adding extensions at the beginning 
-       of the list, make sure it's index is set to 0 (it has ' 0 => ');
+/* List of installed additional modules and plugins. If adding extensions manually 
+       to the list make sure they have unique, so far not used extension_ids as a keys,
+       and $next_extension_id is also updated.
        
        'name' - name for identification purposes;
        'type' - type of extension: 'module' or 'plugin'
        'title' - is the menu text (for plugin) or new tab name
        'active' - current status of extension
        'acc_file' - (optional) file name with $security_areas/$security_sections extensions; 
-               related to 'path'.
+               related to 'path'
+       'access' - security area code in string form
 */
 
+$next_extension_id = 1; // unique id for next installed extension
+
 $installed_extensions = array (
        );
 ?>
\ No newline at end of file