Restricted Adminmenu for users

Please post answers on the most frequently asked questions about CMSimple
Post Reply
cmb
Posts: 12718
Joined: Tue Jun 21, 2011 11:04 am
Location: Mü-Sa, RLP, DE
Contact:

Restricted Adminmenu for users

Post by cmb » Sun Feb 26, 2017 1:24 pm

There's also German documentation about this.

While CMSimple_XH is not supposed to be a multi-user system, it is sometimes desirable to differentiate between a user who should not have access to the full administration, and the admin who should. This is basically impossible without making modifications throughout the code base, but sometimes a simple workaround may be sufficient.

This workaround is showing only a restricted adminmenu to the user, but let the admin have access to the full adminmenu. This can be implemented rather easily by using the possibility to use a custom adminmenu (what is available as of CMSimple_XH 1.6).

I'm offering an example. Put the following code into cmsimple/userfuncs.php:

Code: Select all

<?php

function custom_adminmenu($plugins = array())
{
    if (isset($_GET['real_admin']) || isset($_COOKIE['real_admin'])) {
        setcookie('real_admin', 1, 0);
        return XH_adminMenu($plugins);
    } else {
        return user_adminMenu($plugins);
    }
}

function user_adminMenu($plugins = array())
{
    global $sn, $edit, $s, $u, $cf, $tx, $su, $plugin_tx;

    if ($s < 0) {
        $su = $u[0];
    }
    $changeMode = $edit ? 'normal' : 'edit';
    $changeText = $edit ? $tx['editmenu']['normal'] : $tx['editmenu']['edit'];

    $filesMenu = array();
    foreach (array('images', 'downloads', 'media') as $item) {
        $filesMenu[] =  array(
            'label' => utf8_ucfirst($tx['editmenu'][$item]),
            'url' => $sn . '?&normal&' . $item
        );
    }
    $settingsMenu = array(
        array(
            'label' => utf8_ucfirst($tx['editmenu']['configuration']),
            'url' => $sn . '?file=config&action=array'
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['language']),
            'url' => $sn . '?file=language&action=array'
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['template']),
            'url' => $sn . '?file=template&action=edit'
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['stylesheet']),
            'url' => $sn . '?file=stylesheet&action=edit'
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['log']),
            'url' => $sn . '?file=log&action=view'
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['validate']),
            'url' => $sn . '?&validate'
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['backups']),
            'url' => $sn . '?&xh_backups'
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['pagedata']),
            'url' => $sn . '?&xh_pagedata'
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['sysinfo']),
            'url' => $sn . '?&sysinfo'
        )
    );
    $hiddenPlugins = explode(',', $cf['plugins']['hidden']);
    $hiddenPlugins = array_map('trim', $hiddenPlugins);
    $plugins = array_diff($plugins, $hiddenPlugins);
    $total = count($plugins);
    $rows = 12;
    $columns = ceil($total / $rows);
    $rows = ceil($total / $columns);
    $width = 125 * $columns;
    $marginLeft = min($width, 250) - $width;
    natcasesort($plugins);
    $plugins = array_values($plugins);
    $orderedPlugins = array();
    for ($j = 0; $j < $rows; ++$j) {
        for ($i = 0; $i < $total; $i += $rows) {
            $orderedPlugins[] = isset($plugins[$i + $j]) ? $plugins[$i + $j] : '';
        }
    }
    $plugins = $orderedPlugins;
    $pluginMenu = array();
    foreach ($plugins as $plugin) {
        $label = isset($plugin_tx[$plugin]['menu_plugin'])
            ? $plugin_tx[$plugin]['menu_plugin']
            : ucfirst($plugin);
        $pluginMenuItem = array('label' => $label);
        if ($plugin != '') {
            $pluginMenuItem['url'] = $sn . '?' . $plugin . '&normal';
            foreach (XH_registerPluginMenuItem($plugin) as $item) {
                $pluginMenuItem['children'][] = $item;
            }
        }
        $pluginMenu[] = $pluginMenuItem;
    }
    $menu = array(
        array(
            'label' => $changeText,
            'url' => $sn . '?' . $su . '&' . $changeMode,
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['pagemanager']),
            'url' => $sn . '?&normal&xhpages'
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['files']),
            'url' => $sn . '?&normal&userfiles',
            'children' => $filesMenu
            ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['plugins']),
            'url' => $sn, // TODO: use more sensible URL
            'id' => 'xh_adminmenu_plugins',
            'children' => array()
        ),
        array(
            'label' => utf8_ucfirst($tx['editmenu']['logout']),
            'url' => $sn . '?&logout'
        )
    );

    $t = "\n" . '<div id="xh_adminmenu">';
    $t .= "\n" . '<ul>' . "\n";
    foreach ($menu as $item) {
        $t .= XH_adminMenuItem($item);
    }
    $t .= '</ul>' . "\n"
        . '<div class="xh_break"></div>' . "\n" . '</div>' . "\n";
    return $t;
}
 
Then modifiy cmsimple/config.php and replace the following line:

Code: Select all

$cf['editmenu']['external']="";
with:

Code: Select all

$cf['editmenu']['external']="custom_adminmenu";
After login, the "Settings" menu is completely gone, and the "Plugins" menu doesn't show any plugins. If you want to switch to the "real_admin" mode, just browse to your site with the respective query string appended, e.g. http://example.com/?real_admin. Then you have access to the full admin menu, and also a cookie will be set, so that you don't have to enter the ?real_admin over and over again. The cookie will be valid until you close the browser.

Of course it is possible to further modify the restricted admin menu; see function custom_adminmenu() (in cmsimple/userfuncs.php) which is basically a slightly modified copy of XH_adminMenu() (in cmsimple/adminfuncs.php). The code is supposed to be somewhat self-explaining.

Important note: even if the user can't see some menu items, they still can browse to the hidden functionality by manually entering the appropriate URL in the browser's address bar!
Last edited by cmb on Thu Mar 16, 2017 1:13 pm, edited 1 time in total.
Reason: add link to German documentation
Christoph M. Becker –Plugins for CMSimple_XH, but not for CMSimple 4+

Post Reply