Skip to content

Access control

The package provides some convenient methods to control how the users access the different features provided by the file manager, such as creating a folder, upload a file or deleting it. With granular control in mind, you can use these methods to build your access control flow with freedom and flexibility.

Showing or hiding buttons

Say for instance your app relies on a role/permission based system, in which you may want to grant the ability of creating folder to only a subset of your users. For this, you can use specific methods on your field to show the different action buttons avaiable in the browser modal.

Available methods :

  • showCreateFolder
  • showRenameFolder
  • showDeleteFolder
  • showUploadFile
  • showRenameFile
  • showDeleteFile
  • showCropImage

The usage is pretty straightforward, you can pass a callback that takes the current NovaRequest as a parameter, that resolves into true|false, like so :

// app/Nova/Project.php

use Oneduo\NovaFileManager\FileManager;
use Oneduo\NovaFileManager\Http\Requests\CreateFolderRequest;
use Illuminate\Support\Facades\Storage;
use Laravel\Nova\Http\Requests\NovaRequest;

class Project extends Resource
{
    // ...

    public function fields(NovaRequest $request): array
    {
        return [
            // ... any other fields
            FileManager::make(__('Attachments'), 'attachments')
                ->showCreateFolder(function (NovaRequest $request): bool {
                    // in this instance we only allow the creation of folders to users that pass the `isAdmin()` check
                    return $request->user()?->isAdmin();
                }),
        ];
    }
}

NOTE

Using one of these methods does impact the resolution of the API call associated with the desired action. In other words, in the previous example, setting the visibility of the create folder button to only admin in our app, does in fact prevent all API requests that do not match this condition. Preventing the creation of a folder by a non-admin user.

Restricting access to specific actions

The file manager does provide methods to restrict the access to the different actions based on your own logic if needed. Like the previous example, we can use the following method to implement granular access control :

Available methods :

  • canCreateFolder
  • canRenameFolder
  • canDeleteFolder
  • canUploadFile
  • canRenameFile
  • canDeleteFile

Unlike the show prefixed methods, these aformentionned methods do not hide the buttons from the tool, they only restrict the underlying API actions.

To use these methods, you can pass a callback that takes the corresponding request as a parameter, for instance, upon creating a folder, you can use the following callback :

// app/Nova/Project.php

use Oneduo\NovaFileManager\FileManager;
use Oneduo\NovaFileManager\Http\Requests\CreateFolderRequest;
use Illuminate\Support\Facades\Storage;
use Laravel\Nova\Http\Requests\NovaRequest;

class Project extends Resource
{
    // ...

    public function fields(NovaRequest $request): array
    {
        return [
            // ... any other fields
            FileManager::make(__('Attachments'), 'attachments')
                ->canCreateFolder(function (CreateFolderRequest $request) {
                    // in this example we only allow the creation of folders for users that have the corresponding ability
                    return $request->user()?->can('create-folder');
                }),
        ];
    }
}

You can even go the extra mile and customize the callback to, for example, throw a ValidationException with a custom error message that you can set yourself :

// app/Nova/Project.php

use Oneduo\NovaFileManager\FileManager;
use Oneduo\NovaFileManager\Http\Requests\CreateFolderRequest;
use Illuminate\Support\Facades\Storage;
use Laravel\Nova\Http\Requests\NovaRequest;

class Project extends Resource
{
    // ...

    public function fields(NovaRequest $request): array
    {
        return [
            // ... any other fields
            NovaFileManager::make()
                ->canDeleteFolder(function (DeleteFolderRequest $request) {
                    // check if the current user has the ability to delete the selected folder using its path
                    if (!$request->user()?->can('delete-folder', ['folder' => $request->input('path')])) {
                    
                        throw ValidationException::withMessages([
                            // folder for folder operations, and file for file operations
                            // must return a string[]
                            'folder' => [
                                'You are not allowed to delete this folder',
                            ],
                        ]);
                        
                    }
    
                    return true;
                }),
        ];
    }
}

Specific disk

By default, the package shows the file manager using the configured disks. However, you may want to define a particular disk or folder based on your own business logic.

For instance, having a role/permission based app, let's say you have 2 user groups, Managers and Employees. You want to restrict each user group inside a closed user-land filesystem, in such a way that no user group can access the other user group's files.

Typically, this can be done by having two filesystem disks defined in your filesystems.php and setting the root for each.

// config/filesystems.php

return [
    // ...  
    'disks' => [
        // ...
        'managers' => [
            'driver' => 'local',
            'root' => storage_path('app/public/managers'),
            'url' => env('APP_URL').'/storage/managers',
            'visibility' => 'public',
            'throw' => false,
        ],
        'employees' => [
            'driver' => 'local',
            'root' => storage_path('app/public/employees'),
            'url' => env('APP_URL').'/storage/employees',
            'visibility' => 'public',
            'throw' => false,
        ],
    ],
];

To do so, you may use the filesystem() method, which takes a callback as a parameter, that takes the current NovaRequest as a parameter, and returns a string or a \Illuminate\Contracts\Filesystem\Filesystem instance.

// app/Nova/Project.php

use Oneduo\NovaFileManager\FileManager;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Facades\Storage;
use Laravel\Nova\Http\Requests\NovaRequest;

class Project extends Resource
{
    // ...

    public function fields(NovaRequest $request): array
    {
        return [
            // ... any other fields
            FileManager::make(__('Attachments'), 'attachments')
                ->filesystem(function (NovaRequest $request): string|Filesystem {
                    return $request->user()->role === 'manager' ? 'managers' : 'employees';
                }),
        ];
    }
}

On-demand filesystem

In addition, our tool grants you the ability to define the filesystem on the fly, based on your own logic.

In the example below, you build an on-demand disk that has a root, a folder based on the current user's role :

// app/Nova/Project.php

use Oneduo\NovaFileManager\FileManager;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Facades\Storage;
use Laravel\Nova\Http\Requests\NovaRequest;

class Project extends Resource
{
    // ...

    public function fields(NovaRequest $request): array
    {
        return [
            // ... any other fields
            FileManager::make(__('Attachments'), 'attachments')
                ->filesystem(function (NovaRequest $request): string|Filesystem {
                    // create a filesystem on user basis
                    return Storage::build([
                        'driver' => 'local', // you may use any of the Laravel's builtin filesystem drivers
                        'root' => storage_path('app/public/'.$request->user()->role()), // for a "manager" the root is "storage/app/public/manager"
                        'url' => config('app.url').'/storage/'.$request->user()->role(), // for a "manager" the url is built using http://localhost/storage/manager
                    ]);
                }),
        ];
    }
}

Upload with an existing file name

By default, when you upload a file at a path which already contains a file with the same name a validation error will be thrown. You may want the file to be replaced by the upload. You can change the configuration to always replace existing file in the Configuration file. You can also do it programmatically by using the uploadReplaceExisting method on your tool, field or wrapper.

// app/Nova/Project.php

use Oneduo\NovaFileManager\FileManager;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Facades\Storage;
use Laravel\Nova\Http\Requests\NovaRequest;

class Project extends Resource
{
    // ...

    public function fields(NovaRequest $request): array
    {
        return [
            // ... any other fields
            FileManager::make(__('Attachments'), 'attachments')
                ->uploadReplaceExisting(function (NovaRequest $request): bool {
                    return true;
                }),
        ];
    }
}