silverstripe

Filter Files that the current user has permissions to view


I want to query the files against a search term, and only show the files the current user has permissions to view.

    $files_basic = File::get()->filterAny([
      'Title:PartialMatch' => $s,
      'FileFilename:PartialMatch' => $s,
      'Description:PartialMatch' => $s,
      'DisplayName:PartialMatch' => $s
    ]);

How can I add that filter to my query above?

I know I can restrict the file in the template:

 <% if $canView %>

However that is insufficient as I don't want to fetch not-allowed records and include them at all in the displayed list, pagination counts etc.


Solution

  • Filter file permissions as part of the query (the really hard way):

    What you want is theoretically possible but in almost all cases not practical.

    The information what user can view what file is not a simple direct database relation that you can query. If you want to do it at query time, you have to:

    additionally, you should make sure that there is no additional php based permission checking done by any extension that expends canView of file/folder


    Filter in php with canView right after the query (the more practical way):

    Unless you really have a query that needs to fetch thousands of files, the more practical solution is to fetch all files and then loop/filter them in php. In most cases, this is "fast enough" and much easier to do.

    Using canView in php instead of the template means you can still do things like pagination and correct row counts.

    The Silverstripe ORM provides ->filterByCallback() for ease of use instead of looping. But keep in mind that performance wise this is the same as a foreach (because internally it fetches the whole list and runs a foreach)

     $member = \SilverStripe\Security\Security::getCurrentUser();
     $files_basic = File::get()->filterAny([
          'Title:PartialMatch' => $s,
          'FileFilename:PartialMatch' => $s,
          'Description:PartialMatch' => $s,
          'DisplayName:PartialMatch' => $s
    ])->filterByCallback(function($file) use ($member) {
          // return false will remove the item from the list
          return $file->canView($member);
    });