🔒 Implement signed media URLs and migrate media storage to private disk

-  Introduce `getSignedMediaUrl` in models for temporary signed URLs
- 🗂️ Migrate media collections to private disk for added security
- 🔧 Add `media:move-to-private` command to streamline migration
- ⚙️ Update views and components to use signed media URLs
- ✏️ Adjust route `media.signed` for signed file access handling
This commit is contained in:
HolgerHatGarKeineNode
2026-01-25 19:14:49 +01:00
parent fe2f321a12
commit 10dac9d02b
11 changed files with 335 additions and 5 deletions

View File

@@ -67,6 +67,7 @@ class Course extends Model implements HasMedia
'image/gif',
'image/webp',
])
->useDisk('private')
->useFallbackUrl(asset('img/einundzwanzig.png'));
$this->addMediaCollection('images')
->acceptsMimeTypes([
@@ -75,9 +76,20 @@ class Course extends Model implements HasMedia
'image/gif',
'image/webp',
])
->useDisk('private')
->useFallbackUrl(asset('img/einundzwanzig.png'));
}
public function getSignedMediaUrl(string $collection = 'logo', int $expireMinutes = 60): string
{
$media = $this->getFirstMedia($collection);
if (! $media) {
return asset('img/einundzwanzig.png');
}
return url()->temporarySignedRoute('media.signed', now()->addMinutes($expireMinutes), ['media' => $media]);
}
public function createdBy(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');

View File

@@ -69,6 +69,7 @@ class Lecturer extends Model implements HasMedia
'image/gif',
'image/webp',
])
->useDisk('private')
->useFallbackUrl(asset('img/einundzwanzig.png'));
$this->addMediaCollection('images')
->acceptsMimeTypes([
@@ -77,9 +78,20 @@ class Lecturer extends Model implements HasMedia
'image/gif',
'image/webp',
])
->useDisk('private')
->useFallbackUrl(asset('img/einundzwanzig.png'));
}
public function getSignedMediaUrl(string $collection = 'avatar', int $expireMinutes = 60): string
{
$media = $this->getFirstMedia($collection);
if (! $media) {
return asset('img/einundzwanzig.png');
}
return url()->temporarySignedRoute('media.signed', now()->addMinutes($expireMinutes), ['media' => $media]);
}
/**
* Get the options for generating the slug.
*/

View File

@@ -79,9 +79,20 @@ class Meetup extends Model implements HasMedia
'image/gif',
'image/webp',
])
->useDisk('private')
->useFallbackUrl(asset('img/einundzwanzig.png'));
}
public function getSignedMediaUrl(string $collection = 'logo', int $expireMinutes = 60): string
{
$media = $this->getFirstMedia($collection);
if (! $media) {
return asset('img/einundzwanzig.png');
}
return url()->temporarySignedRoute('media.signed', now()->addMinutes($expireMinutes), ['media' => $media]);
}
public function createdBy(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');

View File

@@ -73,9 +73,20 @@ class ProjectProposal extends Model implements HasMedia
'image/gif',
'image/webp',
])
->useDisk('private')
->useFallbackUrl(asset('einundzwanzig-alpha.jpg'));
}
public function getSignedMediaUrl(string $collection = 'main', int $expireMinutes = 60): string
{
$media = $this->getFirstMedia($collection);
if (! $media) {
return asset('einundzwanzig-alpha.jpg');
}
return url()->temporarySignedRoute('media.signed', now()->addMinutes($expireMinutes), ['media' => $media]);
}
public function einundzwanzigPleb(): BelongsTo
{
return $this->belongsTo(EinundzwanzigPleb::class);

View File

@@ -69,9 +69,20 @@ class Venue extends Model implements HasMedia
'image/gif',
'image/webp',
])
->useDisk('private')
->useFallbackUrl(asset('img/einundzwanzig.png'));
}
public function getSignedMediaUrl(string $collection = 'images', int $expireMinutes = 60): string
{
$media = $this->getFirstMedia($collection);
if (! $media) {
return asset('img/einundzwanzig.png');
}
return url()->temporarySignedRoute('media.signed', now()->addMinutes($expireMinutes), ['media' => $media]);
}
/**
* Get the options for generating the slug.
*/