Restricting access to certain files and files of subdirectories

Hey,

I need some emergency help.
Right now there are certain files accessible which shouldn’t be via the media urls…

I’ve had a route set as follows


		[
			'pattern' => 'media/pages/intern/(:any)',
			'action'  => function ($filename) {
        if($user = kirby()->user()){
          if (in_array($user->role(), ['admin', 'employee'])){
          return $file->download();
          }
        }
        go('login');
			  },
		],

But this doesn’t seem to be doing anything.
Any file of the ‘intern’ subdirectory should be inaccessible unless certain user roles are logged in.
How can I achieve this?

You cannot intercept the media path. Restricting access to files needs a bit more work, see

I’m feeling pretty dumb at the moment.

I’ve copied the cookbook snippet and replaced the template name with the file template and page slug that I want to make inaccessible.
I’m trying it with a file that is a part of the /intern subdirectory and hope for it to redirect once I reload on the browser where I am not logged in.
However it doesn’t seem to be working like this :confused:

<?php

use Kirby\Cms\Response;

Kirby::plugin('cookbook/files-firewall', [
  'routes'       => [
    [
      'pattern' => 'intern/(:any)',
      'action' => function ($filename) {
        if ($user = kirby()->user()) {
          if (
            in_array($user->role(), ['admin', 'employee']) &&
            ($page = page('intern')) &&
            $file = $page->files()->findBy('filename', $filename)
          ) {

            return $file->download();

          }
        }
        return page('login');
      },
    ],
  ],
  'components'   => [
    'file::url' => function ($kirby, $file) {
      if ($file->template() === 'intern') {
        return $kirby->url() . '/' . $file->parent()->id() . '/' . $file->filename();
      }
      return $file->mediaUrl();
    },
    'file::version' => function ($kirby, $file, array $options = []) {

      static $original;

      // if the file is protected, return the original file
      if ($file->template() === 'intern') {
        return $file;
      }
      // if static $original is null, get the original component
      if ($original === null) {
          $original = $kirby->nativeComponent('file::version');
      }

      // and return it with the given options
      return $original($kirby, $file, $options);
    }
  ],
]);

Not sure what you mean with redirect?

sorry, that was the wrong word.
But the user should end up at a login page if they aren’t logged in.

I think I figured it out… kind of.
It only works with files on the first level. The issue now is, that the /intern subdirectory has multiple subdirectories itself. The files within those are still accessible :confused:
But that is probably just a routing issue on my part.

<?php

use Kirby\Cms\Response;

Kirby::plugin('cookbook/files-firewall', [
  'routes' => [
    [
      'pattern' => 'intern/(:any)',
      'action' => function ($filename) {
        if ($user = kirby()->user()) {
          if (
            in_array($user->role(), ['admin', 'employee', 'employee-intitution']) &&
            in_array($this->template(), ['intern', 'internpage', 'internnews', 'internnewspage']) &&
            $file = $this->files()->findBy('filename', $filename)
          ) {

            return $file->download();

          }
          return $this->next();
        } else{
          return go('login');
        }
      },
    ],
  ],
  'components'   => [
    'file::url' => function ($kirby, $file) {
      if ($file->template() === 'intern') {
        return $kirby->url() . '/' . $file->parent()->id() . '/' . $file->filename();
      }
      return $file->mediaUrl();
    },
    'file::version' => function ($kirby, $file, array $options = []) {

      static $original;

      // if the file is protected, return the original file
      if ($file->template() === 'intern') {
        return $file;
      }
      // if static $original is null, get the original component
      if ($original === null) {
          $original = $kirby->nativeComponent('file::version');
      }

      // and return it with the given options
      return $original($kirby, $file, $options);
    }
  ],
]);

Or not.
The media/pages/intern/ url still gives on access to the file itself…

That URL should not appear anywhere, though, so would be very hard to find out.

The issue is that for some reason the media-URLs appear in Google searches for these files.

I have already added the following rules to the robots.txt as well so that Google will not index these pages anymore

user-agent: *
disallow: /intern/*
disallow: /media/pages/intern/*

Is there no way to directly block access to the media subdirectory?
If so I guess I’ll just have to close it off for a while via htaccess until Google removes these links ://

Is the file still created when you call the media url and remove the files from the media folder? I recall we had this issue in the past, but can’t find it at the moment.

Yes, even after deleting the entire media folder.
When I try to open the same URL, which has been indexed by Google, it creates the media subdirectory and file once again,

For now I blocked the media/pages/intern folder using htaccess.
Which is not the most optimal solution but at least that one works at this moment.

Improving how the files’ firewall works is on the agenda, but currently can’t tell when this will be implemented.