barryvdh / laravel-elfinder

elFinder bundle for Laravel
741 stars 171 forks source link

Seperate Folder per user that is read only to Non authedicated users #80

Open janokary opened 9 years ago

janokary commented 9 years ago

Hi I want to have a separate folder per user. I did it by extending ElfinderController and writing my own showConnector method that is almost identical to the original. I just added a value to $defaults 'path' => Auth::user()->id, I also applied the auth middleware, so only authenticated user can access elfinder. It seems to be working fine. The problem is that the generated urls (with a hash) are working only for the authenticated users but what I would like is to give read only access to non authedicated users as well.

sndrsnk commented 9 years ago

I was also wondering if this were possible.

@janokary I'd be grateful if you could provide me some more information as to how you extended the ElfinderController method, as I'd also like to try and implement the same solution. I've attempted to create my own custom version of the method in a new class over-riding the showConnector method but it doesn't seem to be making a difference.

Also, are you creating the directories upon user creation or will this package do that for me?

Thanks!

janokary commented 9 years ago

Firstly I used laravel's flysystem and actually the local disk but I would love to see this working for every occasion.

So, What I did is that I made a new controller that extends ElfinderController and uses the following

and then rewrote the showConnector with an addition to the defaults of FilesystemAdapter

where

and

private function initfolder(){
if (Auth::check())
{
    $privatedir = strval(Auth::user()->id);
} else {
    $privatedir = '';
}
return $privatedir;
}

Remember to use strval or it wont work on PHP >= 5.6.

So

I simply used this connector in my views.

Yes, the package will create user(n) directory named n (where n is user's id)

I also had to to make some routing for the new controller:

Route::group(array('middleware'=>'auth'),function(){
    Route::match(['post','put','delete'],'connectorext', ['as' => 'elfinder.connectorext', 'uses' => 'Elfinder\ElfinderextController@showConnectorext']);
        });
});
Route::get('connectorext', ['as' => 'elfinder.connectorext', 'uses' => 'Elfinder\ElfinderextController@showConnectorext']);

... to 'protect' post 'put' and 'delete' from non authedicated users and leave only 'get' to public access. I think that this is not enough because authedicated users are exposed to each other so a 'Request' must be writen to do that.

public function showConnectorext()
{
    // user private folder
    $privatedir = $this->initfolder(); //janokary
    $roots = $this->app->config->get('elfinder.roots', []);
    if (empty($roots)) {
      $dirs = (array) $this->app['config']->get('elfinder.dir', []);
      foreach ($dirs as $dir) {
          $roots[] = [
              'driver' => 'LocalFileSystem', // driver for accessing file system (REQUIRED)
              'path' => public_path($dir), // path to files (REQUIRED)
              'URL' => url($dir), // URL to files (REQUIRED)
              'accessControl' => $this->app->config->get('elfinder.access') // filter callback (OPTIONAL)
          ];
      }

      $disks = (array) $this->app['config']->get('elfinder.disks', []);
      foreach ($disks as $key => $root) {
          if (is_string($root)) {
              $key = $root;
              $root = [];
          }
          $disk = app('filesystem')->disk($key);
          if ($disk instanceof FilesystemAdapter) {
              $defaults = [
                  'driver' => 'Flysystem',
                  'filesystem' => $disk->getDriver(),
                  'alias' => $key,
                  'path' => $privatedir, // janokary
              ];
              $roots[] = array_merge($defaults, $root);
          }
      }
  }

  $opts = $this->app->config->get('elfinder.options', array());
  $opts = array_merge(['roots' => $roots], $opts);

  // run elFinder
  $connector = new Connector(new \elFinder($opts));
  $connector->run();
  return $connector->getResponse();
  }
eugtw commented 8 years ago

i kind of did it in a very simple way, what do you think? Is it safe?

'path' => public_path($dir).'/'. \Auth::user()->name, // path to files (REQUIRED)
'URL' => url($dir).'/'. \Auth::user()->name, // URL to files (REQUIRED)

in AuthController.php, i added a function to create users' folder when sign up

public function userFolderCreate($username)
    {
        //create user folder
        if(!\File::exists(public_path() . '/files/' . $username)) {
            \File::makeDirectory(public_path() . '/files/' . $username);
        }
    }
rebootcode commented 8 years ago

@eugtw your method is not safe, multiple person can have same name and you will make people with similar name folder shareable to each other.

hondaman900 commented 6 years ago

@eutgw Why not do the same with \Auth::user()->id instead for the folder name to get a unique folders? That would ensure that you don't provide access or have clashes between users with the same username.

roniecurto commented 5 years ago

Hi @janokary , First of all, I would like to thank you for sharing your code. I've been struggling to make ElFinder display dynamic folders according to the user role and you did it perfectly (in another way, but was useful).

I've managed to implement your code and it is working just fine.

But here comes my second problem. I'm creating a project in which the user have access to CkEditor and I have integrated it with ElFinder to allow the user to select images from a local disk using ElFinder. After implementing your logic, the path returned from elfinder is not completed with the folder set by initfolder function in ElfinderextController. For example, I've set in config.filesystems:

    'disks' => [
        'public-files' => [
            'driver' => 'local',
            'root' => public_path('files'),
        ],

Then I've updated config.elfinder:

    'disks' => [
        'public-files' => [
            'URL' => asset('files'),
            'alias' => 'User Files',
        ]
    ],

And let's say my user id is 2. After selecting the image in ElFinder to CkEditor the file url should be: localhost/my-project/public/files/2/test.jpg, but it's returning localhost/my-project/public/files/test.jpg which is not the correct path to the file. Since ElFinder is using dynamic folders, I can't set it in config files. I think it must be related to something in ElfinderextController. Did you integrated ElFinder with CkEditor too? Did you have the same problem? If yes, how did you solve it?

**Edit I manage to solve it using dir instead of disks in config.elfinder.

vahidalvandi commented 4 years ago

thanks you , i have same problem for separate folder per user each .. but i cant solve this , please help me

egin10 commented 3 years ago

Hi @roniecurto and @vahidalvandi, I've tried it with tinymce5, so that's work fine on Laravel 8. You could check it here https://gist.github.com/egin10/29aba94dd94e4277e1e52c389ca81e77 and change the method showTinyMCE5 to showCKeditor4. You could find the method on vendor/barryvdh/laravel-elfinder/src/ElfinderController.php and copy it to CustomElfinderController.

hope it worked fine for you.

vahidalvandi commented 3 years ago

i recommend you to use this package https://github.com/alexusmai/laravel-file-manager

manh-dan commented 1 month ago

I wrote a tutorial on implementing Private User Folders in elFinder for a Laravel project, but the article is in Vietnamese. You can use a translation tool to refer to it: https://manhdandev.com/implementing-private-user-folders-with-elfinder-in-laravel.html