8

I let users create posts and upload/attach images to that post via the frontend. This works fine. However, when I restrict the access to the Wordpress backend (/wp-admin/) via a code snippet like this one

function wpse_11244_restrict_admin() {
    if ( ! current_user_can( 'manage_options' ) ) {
        wp_die( __('You are not allowed to access this part of the site') );
    }
}
add_action( 'admin_init', 'wpse_11244_restrict_admin', 1 );

or (EDIT) with a redirect code

function redirect_non_admin_users() {
    if ( ! current_user_can( 'manage_options' ) && '/wp-admin/admin-ajax.php' != $_SERVER['PHP_SELF'] ) {
        wp_redirect( home_url() );
        exit;
    }
}
add_action( 'admin_init', 'redirect_non_admin_users' );

the Media Upload does not work anymore ("Error" Message). This problem has been discussed elsewhere:

I figured out that if the role didn't have that access [to the backend], it also killed their ability to upload files on the front end.

Is there a way to prevent users to access the backend without killing their ability to upload images on the frontend?

Thank you!

3
  • 1
    It may be a better option to look into redirecting people trying to access anything /wp-admin/ so you're not messing with permissions. – Howdy_McGee Apr 10 '14 at 13:53
  • Same problem, "An Error occurred in the upload. Please try again later". (See my Edit for the redirect code snippet) – SPi Apr 10 '14 at 15:29
  • 1
    How exactly are you implementing upload? – Rarst Apr 10 '14 at 19:00
1

First, it is important to consider why you are restricting access to wp-admin. If you are doing this mainly for aesthetic purposes, then the solution provided below is fine. However, if you are doing it because you don't want your users to be able to perform certain functions provided via the back-end, you should be using WordPress's built-in roles and capabilities API instead. Give your users a role with only those capabilities that you want them to have. Otherwise, granting access to the Ajax actions will probably allow them to do things that you were trying to prevent them from doing.

Which brings us to the cause of your problem. Ajax is involved in uploading the image, and the Ajax handler (wp-admin/admin-ajax.php) is technically back-end, even when called from the front end. So your code hooked to 'admin_init' is being triggered. What you need to do is check if the request is an Ajax request in that function, and only exit/redirect if it is not. Since WP 4.7, you can now use the wp_doing_ajax() function for this.

function redirect_non_admin_users() {
    if ( wp_doing_ajax() ) {
        return; // Don't block Ajax requests.
    }

    if ( ! current_user_can( 'manage_options' ) && '/wp-admin/admin-ajax.php' != $_SERVER['PHP_SELF'] ) {
        wp_redirect( home_url() );
        exit;
    }
}
add_action( 'admin_init', 'redirect_non_admin_users' );

If you only want to allow your users access to uploading attachments, you could probably change the condition to this:

    if ( wp_doing_ajax() && isset( $_POST['action'] ) && 'upload-attachment' === $_POST['action'] ) {
        return; // Don't block attachment upload requests.
    }

However, note that many plugins provide their own Ajax actions as well, which would be blocked in this case. So you will be better off using the role and capability API, as stated above.

5
  • it is just wrong. blocking functionality should be based on capabilities not from where a request came. Basically this just repeats the mistake of the OP, just the other way around (being too relaxed) – Mark Kaplun Oct 11 '17 at 5:53
  • @MarkKaplun Of course. But in this case we aren't restricting just a particular feature. If you are going to restrict wp-admin completely, but still need to allow for Ajax requests, I'm not sure how else you would do it. Of course each Ajax callback should have its own capability checks, but that is a separate issue as far as I can see. This won't override any capability checks that the Ajax callbacks do themselves. It doesn't affect the Ajax callbacks at all, only the ability to access the back-end. That is the only thing that the OP said they wanted to restrict. Not the Ajax actions. :-) – J.D. Oct 11 '17 at 12:44
  • I guess I assumed that because the OP is still allowing users to perform these kinds of actions, hiding the back end is mainly just aesthetics. Of course, if that isn't the case then they do need to consider more carefully what capabilities they are giving users. – J.D. Oct 11 '17 at 12:46
  • @MarkKaplun I've just updated the answer to clarify that the role and capability API should be used instead if you are trying to restrict access to particular features, and not just the back-end interface. – J.D. Oct 11 '17 at 13:38
  • I guess the problem is with restricting ajax in the first place. so many plugins will break with that it is not funny. As for checking if you are doing AJAX, for me it is a false sense of security which might make you an easier victim of privilege escalation attacks. Actually would have downvoted the question, but with 5 upvotes it is pointless – Mark Kaplun Oct 11 '17 at 13:41
0

Keeping it simple, there are two plugins that I use to achieve the same thing you seek effectively:

  1. WP Admin No SHow : https://wordpress.org/plugins/wp-admin-no-show/

  2. Redirect After Login: https://wordpress.org/plugins/redirect-after-login/

The first option allows you to select multiple roles and redirect them when they seek to access wp-admin The second option gives you the option to redirect individual roles when they login.

Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.