Restrict both media library and media attachment page per user login

I am attempting to implement a solution that allows (1) users to have truly private files and (2) lets admin see all files. Many of the solutions that exist only restrict media on the backend, but if another user had or guessed the actual file URL they would still be able download it even without it being displayed in the media library.

I attempted the accepted solution in this question:
How to restrict attachment download to a specific user?

However I’m getting 404 redirects even for user owned files. I am reposting the shortened accepted solution here:

1. Define a query variable that indicates the requested file

function add_get_file_query_var( $vars ) {
$vars[] = ‘get_file’;
return $vars;
}
add_filter( ‘query_vars’, ‘add_get_file_query_var’ );

2. Update .htaccess to forward requests for restricted files to WordPress

RewriteRule ^wp-content/uploads/(.*.docx)$ /index.php?get_file=$1

3. Capture the requested file name in custom query variable; and verify access to the file:

function intercept_file_request( $wp ) {
if( !isset( $wp->query_vars[‘get_file’] ) )
return;

global $wpdb, $current_user;

// Find attachment entry for this file in the database:
$query = $wpdb->prepare(“SELECT ID FROM {$wpdb->posts} WHERE guid=’%s'”, $_SERVER[‘REQUEST_URI’] );
$attachment_id = $wpdb->get_var( $query );

// No attachment found. 404 error.
if( !$attachment_id ) {
$wp->query_vars[‘error’] = ‘404’;
return;
}

// Get post from database
$file_post = get_post( $attachment_id );
$file_path = get_attached_file( $attachment_id );

if( !$file_post || !$file_path || !file_exists( $file_path ) ) {
$wp->query_vars[‘error’] = ‘404’;
return;
}

// Logic for validating current user’s access to this file…
// Option A: check for user capability
if( !current_user_can( ‘required_capability’ ) ) {
$wp->query_vars[‘error’] = ‘404’;
return;
}

// Option B: check against current user
if( $current_user->user_login == “authorized_user” ) {
$wp->query_vars[‘error’] = ‘404’;
return;
}

// Everything checks out, user can see this file. Simulate headers and go:
header( ‘Content-Type: ‘ . $file_post->post_mime_type );
header( ‘Content-Dispositon: attachment; filename=”‘. basename( $file_path ) .'”‘ );
header( ‘Content-Length: ‘ . filesize( $file_path ) );

echo file_get_contents( $file_path );
die(0);
}
add_action( ‘wp’, ‘intercept_file_request’ );

Any ideas why this might not be working, i.e. redirecting the owner of the file to a 404 not found page, instead of allow download?

Read more here:: Restrict both media library and media attachment page per user login

Leave a Reply

Your email address will not be published. Required fields are marked *