Media Library - v1.0-beta1
Permissions & Access Control
The Media Library uses capability-based permissions for fine-grained access control. This guide covers setting up and managing permissions.
Permission Capabilities
The package defines four main capabilities:
media.view- View media librarymedia.upload- Upload new mediamedia.edit- Edit media metadatamedia.delete- Delete media
Policy-Based Authorization
The package uses Laravel Policies for authorization checks:
// In MediaPolicy.php
public function view(User $user, Media $media): bool
{
return $user->hasCapability('media.view');
}
public function create(User $user): bool
{
return $user->hasCapability('media.upload');
}
public function update(User $user, Media $media): bool
{
return $user->hasCapability('media.edit');
}
public function delete(User $user, Media $media): bool
{
return $user->hasCapability('media.delete');
}
Setting Up Roles
Administrator Role
Full access to all media features:
use ArtisanPackUI\CMSFramework\Modules\Users\Models\Role;
$admin = Role::where('slug', 'administrator')->first();
$admin->capabilities = array_merge($admin->capabilities ?? [], [
'media.view',
'media.upload',
'media.edit',
'media.delete',
]);
$admin->save();
Editor Role
Can view, upload, and edit but not delete:
$editor = Role::where('slug', 'editor')->first();
$editor->capabilities = array_merge($editor->capabilities ?? [], [
'media.view',
'media.upload',
'media.edit',
]);
$editor->save();
Author Role
Can view and upload only:
$author = Role::where('slug', 'author')->first();
$author->capabilities = array_merge($author->capabilities ?? [], [
'media.view',
'media.upload',
]);
$author->save();
Contributor Role
Can view only (read-only access):
$contributor = Role::where('slug', 'contributor')->first();
$contributor->capabilities = array_merge($contributor->capabilities ?? [], [
'media.view',
]);
$contributor->save();
Checking Permissions
In Controllers
// Check before action
$this->authorize('view', Media::class);
$this->authorize('create', Media::class);
$this->authorize('update', $media);
$this->authorize('delete', $media);
In Blade Views
@can('view', App\Models\Media::class)
<a href="/admin/media">Media Library</a>
@endcan
@can('create', App\Models\Media::class)
<button>Upload Media</button>
@endcan
@can('update', $media)
<button>Edit</button>
@endcan
@can('delete', $media)
<button>Delete</button>
@endcan
In Code
// Check capability
if (auth()->user()->hasCapability('media.upload')) {
// Allow upload
}
// Check using Gate
if (Gate::allows('create', Media::class)) {
// Allow creation
}
Custom Permission Hooks
Override permission checks using hooks:
// Customize viewAny capability
addFilter('ap.media.viewAny', function($capability) {
return 'custom.media.view';
});
// Customize create capability
addFilter('ap.media.create', function($capability) {
return 'custom.media.upload';
});
// Other available hooks:
// ap.media.view
// ap.media.update
// ap.media.delete
// ap.media.restore
// ap.media.forceDelete
Ownership-Based Permissions
Restrict users to only their own media:
// In MediaPolicy.php
public function update(User $user, Media $media): bool
{
// Check capability
if (!$user->hasCapability('media.edit')) {
return false;
}
// Check ownership
return $media->uploaded_by === $user->id || $user->hasCapability('media.edit.any');
}
Then assign the capability:
// Author can edit only their own media
$author->capabilities = array_merge($author->capabilities ?? [], [
'media.view',
'media.upload',
'media.edit', // Own media only
]);
// Editor can edit any media
$editor->capabilities = array_merge($editor->capabilities ?? [], [
'media.view',
'media.upload',
'media.edit',
'media.edit.any', // Any media
]);
Folder Permissions
Restrict access to specific folders:
// In a custom policy or middleware
public function viewFolder(User $user, MediaFolder $folder): bool
{
// Allow if user has general view capability
if (!$user->hasCapability('media.view')) {
return false;
}
// Check folder-specific permissions
$allowedFolders = $user->settings['allowed_media_folders'] ?? [];
// Empty array means all folders
if (empty($allowedFolders)) {
return true;
}
// Check if folder is in allowed list
return in_array($folder->id, $allowedFolders);
}
API Authentication
API endpoints use the same permission system via Sanctum:
// In routes/api.php
Route::middleware('auth:sanctum')->group(function () {
Route::get('/media', [MediaController::class, 'index']);
Route::post('/media', [MediaController::class, 'store']);
// ... other routes
});
Permissions are checked in controllers:
public function index(Request $request)
{
$this->authorize('viewAny', Media::class);
// ...
}
Testing Permissions
Write tests for permission checks:
test('user without view capability cannot access media', function () {
$user = User::factory()->create();
$response = actingAs($user)->get('/admin/media');
$response->assertForbidden();
});
test('user with view capability can access media', function () {
$role = Role::factory()->create([
'capabilities' => ['media.view'],
]);
$user = User::factory()->create();
$user->roles()->attach($role);
$response = actingAs($user)->get('/admin/media');
$response->assertOk();
});
Next Steps
- Learn about Customization
- Review CMS Module Integration
- See Troubleshooting