Admin can now control channel creation from the admin dashboard
This commit is contained in:
73
app/Http/Controllers/AdminChannelCreationController.php
Normal file
73
app/Http/Controllers/AdminChannelCreationController.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\AdminAuditLog;
|
||||
use App\Models\PlatformSetting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AdminChannelCreationController extends Controller
|
||||
{
|
||||
public function updateDefault(Request $request): RedirectResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'channel_creation_open' => ['required', 'boolean'],
|
||||
]);
|
||||
|
||||
$settings = PlatformSetting::current();
|
||||
|
||||
$settings->forceFill([
|
||||
'channel_creation_open' => (bool) $validated['channel_creation_open'],
|
||||
])->save();
|
||||
|
||||
$this->audit($request, $settings, 'platform.channel_creation_default.updated', [
|
||||
'channel_creation_open' => $settings->channel_creation_open,
|
||||
]);
|
||||
|
||||
return back()->with(
|
||||
'success',
|
||||
$settings->channel_creation_open
|
||||
? 'All verified users can create channels.'
|
||||
: 'Channel creation now requires admin approval.',
|
||||
);
|
||||
}
|
||||
|
||||
public function updateUser(Request $request, User $user): RedirectResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'can_create_channel' => ['required', 'boolean'],
|
||||
]);
|
||||
|
||||
$user->forceFill([
|
||||
'can_create_channel' => (bool) $validated['can_create_channel'],
|
||||
])->save();
|
||||
|
||||
$this->audit($request, $user, 'user.creator_access.updated', [
|
||||
'can_create_channel' => $user->can_create_channel,
|
||||
]);
|
||||
|
||||
return back()->with(
|
||||
'success',
|
||||
$user->can_create_channel
|
||||
? 'User can create a channel.'
|
||||
: 'User channel creation access removed.',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $metadata
|
||||
*/
|
||||
private function audit(Request $request, object $subject, string $action, array $metadata = []): void
|
||||
{
|
||||
AdminAuditLog::query()->create([
|
||||
'admin_user_id' => $request->user()?->id,
|
||||
'subject_type' => $subject::class,
|
||||
'subject_id' => $subject->id,
|
||||
'action' => $action,
|
||||
'metadata' => $metadata === [] ? null : $metadata,
|
||||
'created_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Broadcast;
|
||||
use App\Models\Channel;
|
||||
use App\Models\PlatformSetting;
|
||||
use App\Models\User;
|
||||
use App\Models\Vod;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -20,6 +21,10 @@ class AdminDashboardController extends Controller
|
||||
'channels' => Channel::query()->count(),
|
||||
'live_channels' => Channel::query()->where('is_live', true)->count(),
|
||||
'vods' => Vod::query()->count(),
|
||||
'creator_access_grants' => User::query()->where('can_create_channel', true)->count(),
|
||||
],
|
||||
'channelCreationPolicy' => [
|
||||
'channel_creation_open' => PlatformSetting::current()->channel_creation_open,
|
||||
],
|
||||
'liveBroadcasts' => Broadcast::query()
|
||||
->where('status', Broadcast::STATUS_LIVE)
|
||||
@@ -57,6 +62,25 @@ class AdminDashboardController extends Controller
|
||||
'name' => $channel->user->name,
|
||||
],
|
||||
]),
|
||||
'users' => User::query()
|
||||
->with('channel')
|
||||
->latest('id')
|
||||
->limit(50)
|
||||
->get()
|
||||
->map(fn (User $user) => [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'email' => $user->email,
|
||||
'is_admin' => $user->is_admin,
|
||||
'can_create_channel' => $user->can_create_channel,
|
||||
'suspended_at' => $user->suspended_at?->toIso8601String(),
|
||||
'created_at' => $user->created_at?->toIso8601String(),
|
||||
'channel' => $user->channel ? [
|
||||
'id' => $user->channel->id,
|
||||
'slug' => $user->channel->slug,
|
||||
'display_name' => $user->channel->display_name,
|
||||
] : null,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ class CreatorDashboardController extends Controller
|
||||
|
||||
return Inertia::render('dashboard', [
|
||||
'channel' => $channel ? $this->channelPayload($channel) : null,
|
||||
'canCreateChannel' => $request->user()->canCreateChannel(),
|
||||
'plainStreamKey' => session('plain_stream_key'),
|
||||
'streaming' => [
|
||||
'ingestServer' => $streamKeys->ingestServer(),
|
||||
@@ -57,6 +58,7 @@ class CreatorDashboardController extends Controller
|
||||
public function storeChannel(Request $request, StreamKeyManager $streamKeys): RedirectResponse
|
||||
{
|
||||
abort_if($request->user()->channel()->exists(), 422, 'This account already owns a channel.');
|
||||
abort_unless($request->user()->canCreateChannel(), 403, 'An admin must enable channel creation for this account.');
|
||||
|
||||
$validated = $request->validate([
|
||||
'display_name' => ['required', 'string', 'max:80'],
|
||||
|
||||
26
app/Models/PlatformSetting.php
Normal file
26
app/Models/PlatformSetting.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
#[Fillable(['channel_creation_open'])]
|
||||
class PlatformSetting extends Model
|
||||
{
|
||||
protected $attributes = [
|
||||
'channel_creation_open' => false,
|
||||
];
|
||||
|
||||
public static function current(): self
|
||||
{
|
||||
return static::query()->first() ?? static::query()->create();
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'channel_creation_open' => 'boolean',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,17 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Fortify\TwoFactorAuthenticatable;
|
||||
|
||||
#[Fillable(['name', 'email', 'password', 'is_admin', 'suspended_at'])]
|
||||
#[Fillable(['name', 'email', 'password', 'is_admin', 'can_create_channel', 'suspended_at'])]
|
||||
#[Hidden(['password', 'two_factor_secret', 'two_factor_recovery_codes', 'remember_token'])]
|
||||
class User extends Authenticatable
|
||||
{
|
||||
/** @use HasFactory<UserFactory> */
|
||||
use HasFactory, Notifiable, TwoFactorAuthenticatable;
|
||||
|
||||
protected $attributes = [
|
||||
'can_create_channel' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the attributes that should be cast.
|
||||
*
|
||||
@@ -32,6 +36,7 @@ class User extends Authenticatable
|
||||
'password' => 'hashed',
|
||||
'two_factor_confirmed_at' => 'datetime',
|
||||
'is_admin' => 'boolean',
|
||||
'can_create_channel' => 'boolean',
|
||||
'suspended_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
@@ -50,4 +55,9 @@ class User extends Authenticatable
|
||||
{
|
||||
return $this->suspended_at !== null;
|
||||
}
|
||||
|
||||
public function canCreateChannel(): bool
|
||||
{
|
||||
return $this->can_create_channel || PlatformSetting::current()->channel_creation_open;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user