stancl / tenancy-docs

stancl/tenancy docs & website
https://tenancyforlaravel.com/docs
MIT License
64 stars 627 forks source link

Add spatie/laravel-medialibrary integration guide #194

Closed lukinovec closed 2 years ago

lukinovec commented 2 years ago

https://github.com/stancl/tenancy-docs/issues/78

stancl commented 2 years ago

How did you resolve the issue with the other methods/temporary URLs etc? Just by extending the class instead of creating a new one that implements the interface?

lukinovec commented 2 years ago

How did you resolve the issue with the other methods/temporary URLs etc? Just by extending the class instead of creating a new one that implements the interface?

Yeah. If the custom command extended the abstract class (BaseUrlGenerator) instead, we'd copy the methods from the DefaultUrlGenerator class (except getUrl() which we'd override) because it looks like the methods are working as expected. Extending the class seems better than doing that

abbasmashaddy72 commented 2 months ago

Fixing Media Serving Issues

Hi, I encountered an issue where media files were not being served correctly in a multitenant Laravel application, resulting in 404 errors.

Initially, I followed the standard approach by creating a custom UrlGenerator class to handle the URL generation.

The Issue

Even with this setup, media files continued to return 404 errors, indicating that the generated URLs weren't correctly resolving to the tenant-specific storage paths.

Potential Route Conflict: I also identified that a custom route I had defined might be causing a conflict:

Route::get('{page:slug}', [PageController::class, 'show'])->name('page.show');

This route is very general and could be intercepting requests meant for media files, especially if the filename or media path resembles a slug. This could explain why the media files were not being served as expected.

The Solution

To resolve this, I made the following adjustments:

  1. Custom Tenant-Aware URL Generator: I refined the TenantAwareUrlGenerator class to ensure it generates URLs that correctly point to tenant-specific storage:

    <?php
    
    namespace App\Supports;
    
    use Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator;
    
    class TenantAwareUrlGenerator extends DefaultUrlGenerator
    {
        public function getUrl(): string
        {
            $url = asset('storage/' . $this->getPathRelativeToRoot());
    
            return $this->versionUrl($url);
        }
    }
  2. Route for Serving Media Files: I defined a dedicated route to serve media files, ensuring that the tenant context is respected and files are correctly served:

    <?php
    
    use Illuminate\Support\Facades\Route;
    use Spatie\MediaLibrary\MediaCollections\Models\Media;
    use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
    
    Route::middleware(['web', 'universal', InitializeTenancyByDomain::class])->group(function () {
        Route::get('/storage/{mediaId}/{filename}', function ($mediaId, $filename) {
            // Find the media record by ID
            $media = Media::find($mediaId);
    
            if (! $media) {
                abort(404, 'File not found');
            }
    
            // Get the path to the file within the tenant's storage
            $path = $media->getPath();
    
            // Validate the filename to avoid potential path traversal attacks
            if (basename($path) !== $filename) {
                abort(404, 'File not found');
            }
    
            // Serve the file from the tenant's storage
            return response()->file($path);
        });
    });

Conclusion

These changes resolved the 404 errors and ensured that media files are correctly served from tenant-specific directories. This approach integrates seamlessly with the multitenant setup.