WordPress.org

Ready to get started?Download WordPress

Ideas

Allow hardcoded capabilities in core to be filtered

  1. Eddie Moya
    Member

    12345

    I find it obnoxious that if I need to change the way capabilities are split up across pages, or even if I want to granulize permissions on a particular admin page, that I must modify those core files to do it.

    What seems necessary is a simple way of filtering capabilities on an very granular level, without necessarily flooding the WordPress core with a special cap for every little field.

    There are a few different ways this might be achieved, and honestly what I will show here is my first thoughts as to how to address it. There may be, and probably are better and more efficient ways to accomplish this.

    Take for example the options-general.php page. It doesn't matter really what example I use, but lets say I want to divide certain responsibilities and access on that page. Currently, I would have to modify core files to add capability checks. There are also instances where capabilities currently span multiple pages, and a developer may need to split those up.

    Perhaps the best example is the 'edit_theme_options', which is necessary if you want to grant a user access to edit widgets, but also grants them access to modify things like the header, background, and menus. However,for the sake of simplicity my example will show how we might allow for granularity on options-general.php. In my example I will want to separate one field, specifically for a users who handle with SEO, and have 'seo' as a capability in their roll. Again, the details don't matter here. The example doesn't make perfect sense but the point is the method used to optionally granulize.

    How two fields might look in options-general.php:

    $cap = apply_filters( 'capabilities', 'manage_options' , '1');
    if(current_user_can($cap)){
        ?>
        <tr valign="top">
            <th scope="row"><label for="blogname"><?php _e('Site Title') ?></label></th>
            <td><input name="blogname" type="text" id="blogname" value="<?php form_option('blogname'); ?>" class="regular-text" /></td>
        </tr>
     <?php
    }
    
    $cap = apply_filters( 'capabilities', 'manage_options' , '2');
    
    if(current_user_can($cap)){
        ?>
        <tr valign="top">
            <th scope="row"><label for="home"><?php _e('Site address (URL)') ?></label></th>
            <td><input name="home" type="text" id="home" value="<?php form_option('home'); ?>"<?php disabled( defined( 'WP_HOME' ) ); ?> class="regular-text code<?php if ( defined( 'WP_HOME' ) ) echo ' disabled' ?>" />
            <span class="description"><?php _e('Enter the address here if you want your site homepage <a href="http://codex.wordpress.org/Giving_WordPress_Its_Own_Directory">to be different from the directory</a> you installed WordPress.'); ?></span></td>
        </tr>
     <?php
    }

    Elsewhere, say in a plugin, developers could do something like this to specify a different capability for capability #2

    add_filter('capabilities', 'modify_admin_capabilities', 10, 2);
    function modify_admin_capabilities($capability, $index){
        if($index == 2){
            return "seo";
        }
    }

    Obviously then the developer could add the capability to whater existing or custom roles they want.
    This is a rough concept, and the scheme is certainly flexible. I decided in my example to group what are the current 'manage_options' fields by including the capability in the filter tag. However, we could have a master tag called 'capabilities', and simply have large numerical indexes - that might be harder to maintain as capabilities proliferate.

    There may even be entirely different ways to achieve a similar result. Perhaps have each current instance of a capability check with an indexed array, which can be filtered, and then checked against as you go though all the items on the page.

    In any case, the example above may not be the actual strategy used, but it expresses the essential notion of what I think we should be able to do with those hardcoded capabilities.

    Posted: 3 years ago #
  2. Christopher Carson
    Member

    12345

    I ran into this problem trying to answer a question on Stack Overflow as well as in the course of my own work. current_user_can() definitely needs to implement a filter hook. This require one extra line of code in current_user_can() -- return apply_filters('current_user_can', $cap) -- you'd leave it up to the plugin to figure out what exactly the user is trying to do and decide whether to return true or false.

    In the case I refer to above, we were trying to keep 'authors' from deleting any attachments, including their own, while still being able to 'delete_post'. This is impossible without modifying or replacing wp-admin/upload.php for authors.

    Posted: 3 years ago #
  3. Eddie Moya
    Member

    12345

    @chriscarson You are absolutely right, it would be much simpler to add just the single line to current_user_can, for just the filter. For the mean time, this maybe a partial solution - I think this doesnt solve the problem of scale however.

    When bringing the issue of granularity up, I often get concerns about the proliferation of hooks - if we are to increase granularity while making it filterable, we need a way to keep the number of hooks down.

    you'd leave it up to the plugin to figure out what exactly the user is trying to do and decide whether to return true or false.

    I can see how some items might be 'figured out' by checking the the page your on, or other sparse contextual clues, but I don't see this providing a standard obvious way to differentiate items on a page - also, much of what we mean to block is not based on what a user is trying to do, but rather what we want them not to even see.

    Posted: 3 years ago #
  4. Eddie Moya
    Member

    12345

    A couple weeks ago at WordCamp Chicago, I brought this up with Otto, and he pointed out that this could be easily accomplished via the Settings API. However, as far as I know nothing in the admin backend uses the Settings API.

    So to paraphrase Otto: "We need to make WordPress use its own shit"

    To be honest I have not used the Settings API much myself, I've more or less stuck to the old way of creating plugin interfaces - so I'm a little unfamiliar with how this would work in terms of filtering and granularity. However if this truly is a solution to the problem I'm talking about, I would be definitely be up for an effort to overhaul the admin interface.

    If that seems to make sense to people, and once I wrap my head around how this would work via the settings API, I might make that a new Idea.

    Posted: 3 years ago #

RSS feed for this topic

Reply

You must log in to post.

  • Rating

    12345
    6 Votes
  • Status

    This idea is under consideration