diff --git a/app/Livewire/Agents/CreateAgentForm.php b/app/Livewire/Agents/CreateAgentForm.php index 985d5cd8..244e2f61 100644 --- a/app/Livewire/Agents/CreateAgentForm.php +++ b/app/Livewire/Agents/CreateAgentForm.php @@ -11,6 +11,7 @@ use App\Domain\Tool\Models\Tool; use App\Infrastructure\AI\Enums\ReasoningEffort; use App\Infrastructure\AI\Services\ProviderResolver; +use Illuminate\Support\Facades\Gate; use Illuminate\Validation\Rule; use Livewire\Component; @@ -137,6 +138,8 @@ protected function rules(): array public function save(): void { + Gate::authorize('edit-content'); + $this->validate(); $team = auth()->user()->currentTeam; diff --git a/app/Livewire/Agents/QuickAgentForm.php b/app/Livewire/Agents/QuickAgentForm.php index ad1c47ce..c81b3940 100644 --- a/app/Livewire/Agents/QuickAgentForm.php +++ b/app/Livewire/Agents/QuickAgentForm.php @@ -5,6 +5,7 @@ use App\Domain\Agent\Actions\CreateAgentAction; use App\Domain\Project\Actions\CreateProjectAction; use App\Infrastructure\AI\Services\ProviderResolver; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class QuickAgentForm extends Component @@ -41,6 +42,8 @@ protected function rules(): array public function save(): void { + Gate::authorize('edit-content'); + $this->validate(); $team = auth()->user()->currentTeam; diff --git a/app/Livewire/Chatbots/ChatbotDetailPage.php b/app/Livewire/Chatbots/ChatbotDetailPage.php index 536f156e..ee2cd95f 100644 --- a/app/Livewire/Chatbots/ChatbotDetailPage.php +++ b/app/Livewire/Chatbots/ChatbotDetailPage.php @@ -13,6 +13,7 @@ use App\Domain\Chatbot\Models\ChatbotToken; use App\Domain\Workflow\Models\Workflow; use App\Infrastructure\AI\Services\ProviderResolver; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class ChatbotDetailPage extends Component @@ -67,6 +68,8 @@ public function mount(Chatbot $chatbot): void public function toggleStatus(): void { + Gate::authorize('edit-content'); + app(ToggleChatbotStatusAction::class)->execute($this->chatbot); $this->chatbot->refresh(); session()->flash('message', 'Chatbot status updated.'); @@ -94,6 +97,8 @@ public function cancelEdit(): void public function saveEdit(): void { + Gate::authorize('edit-content'); + $this->validate([ 'editName' => 'required|min:2|max:255', 'editConfidenceThreshold' => 'required|numeric|min:0.1|max:1.0', @@ -124,6 +129,8 @@ public function saveEdit(): void public function generateToken(): void { + Gate::authorize('edit-content'); + $this->validate([ 'newTokenName' => 'required|min:1|max:100', ]); @@ -144,6 +151,8 @@ public function generateToken(): void public function revokeToken(string $tokenId): void { + Gate::authorize('edit-content'); + $token = ChatbotToken::where('id', $tokenId) ->where('chatbot_id', $this->chatbot->id) ->firstOrFail(); @@ -181,6 +190,8 @@ public function cancelTelegramForm(): void public function saveTelegramChannel(): void { + Gate::authorize('edit-content'); + $this->validate([ 'telegramBotToken' => 'required|string|min:10', 'telegramWebhookSecret' => 'nullable|string|max:256', @@ -211,6 +222,8 @@ public function saveTelegramChannel(): void public function toggleTelegramChannel(string $channelId): void { + Gate::authorize('edit-content'); + $channel = ChatbotChannel::where('id', $channelId) ->where('chatbot_id', $this->chatbot->id) ->firstOrFail(); @@ -220,6 +233,8 @@ public function toggleTelegramChannel(string $channelId): void public function deleteTelegramChannel(string $channelId): void { + Gate::authorize('edit-content'); + ChatbotChannel::where('id', $channelId) ->where('chatbot_id', $this->chatbot->id) ->delete(); @@ -229,6 +244,8 @@ public function deleteTelegramChannel(string $channelId): void public function delete(): void { + Gate::authorize('edit-content'); + app(DeleteChatbotAction::class)->execute($this->chatbot); session()->flash('message', 'Chatbot deleted.'); diff --git a/app/Livewire/Chatbots/CreateChatbotForm.php b/app/Livewire/Chatbots/CreateChatbotForm.php index 8c5baf65..e783b637 100644 --- a/app/Livewire/Chatbots/CreateChatbotForm.php +++ b/app/Livewire/Chatbots/CreateChatbotForm.php @@ -6,6 +6,7 @@ use App\Domain\Chatbot\Actions\CreateChatbotAction; use App\Domain\Chatbot\Enums\ChatbotType; use App\Infrastructure\AI\Services\ProviderResolver; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class CreateChatbotForm extends Component @@ -58,6 +59,8 @@ protected function rules(): array public function save(): void { + Gate::authorize('edit-content'); + $this->validate(); $team = auth()->user()->currentTeam; diff --git a/app/Livewire/Credentials/CreateCredentialForm.php b/app/Livewire/Credentials/CreateCredentialForm.php index 1a6bc89d..0ecd1bf1 100644 --- a/app/Livewire/Credentials/CreateCredentialForm.php +++ b/app/Livewire/Credentials/CreateCredentialForm.php @@ -4,6 +4,7 @@ use App\Domain\Credential\Actions\CreateCredentialAction; use App\Domain\Credential\Enums\CredentialType; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class CreateCredentialForm extends Component @@ -120,6 +121,8 @@ public function removeCustomPair(int $index): void public function save(): void { + Gate::authorize('edit-content'); + $team = auth()->user()->currentTeam; $type = CredentialType::from($this->credentialType); $secretData = $this->buildSecretData($type); diff --git a/app/Livewire/Credentials/CredentialDetailPage.php b/app/Livewire/Credentials/CredentialDetailPage.php index 36d2733a..74eca6fd 100644 --- a/app/Livewire/Credentials/CredentialDetailPage.php +++ b/app/Livewire/Credentials/CredentialDetailPage.php @@ -15,6 +15,7 @@ use App\Domain\Credential\Models\Credential; use App\Domain\Credential\Models\CredentialVersion; use App\Domain\Project\Models\Project; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class CredentialDetailPage extends Component @@ -66,6 +67,8 @@ public function mount(Credential $credential): void public function toggleStatus(): void { + Gate::authorize('edit-content'); + $newStatus = $this->credential->status === CredentialStatus::Active ? CredentialStatus::Disabled : CredentialStatus::Active; @@ -76,6 +79,8 @@ public function toggleStatus(): void public function approveCredential(): void { + Gate::authorize('edit-content'); + $approvalRequest = ApprovalRequest::withoutGlobalScopes() ->where('credential_id', $this->credential->id) ->where('status', ApprovalStatus::Pending) @@ -94,6 +99,8 @@ public function approveCredential(): void public function rejectCredential(string $reason = 'Rejected by reviewer'): void { + Gate::authorize('edit-content'); + $approvalRequest = ApprovalRequest::withoutGlobalScopes() ->where('credential_id', $this->credential->id) ->where('status', ApprovalStatus::Pending) @@ -125,6 +132,8 @@ public function cancelEdit(): void public function save(): void { + Gate::authorize('edit-content'); + $this->validate([ 'editName' => 'required|min:2|max:255', 'editDescription' => 'max:1000', @@ -168,6 +177,8 @@ public function removeRotateCustomPair(int $index): void public function rotateSecret(): void { + Gate::authorize('edit-content'); + $type = $this->credential->credential_type; // Validate rotation based on type diff --git a/app/Livewire/Crews/CreateCrewForm.php b/app/Livewire/Crews/CreateCrewForm.php index 68e3724e..5362938c 100644 --- a/app/Livewire/Crews/CreateCrewForm.php +++ b/app/Livewire/Crews/CreateCrewForm.php @@ -7,6 +7,7 @@ use App\Domain\Crew\Actions\CreateCrewAction; use App\Domain\Crew\Actions\GenerateCrewFromPromptAction; use App\Domain\Crew\Enums\CrewProcessType; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class CreateCrewForm extends Component @@ -64,6 +65,8 @@ protected function rules(): array public function generateFromPrompt(GenerateCrewFromPromptAction $action): void { + Gate::authorize('edit-content'); + $this->validate(['generatePrompt' => 'required|string|min:10']); $this->generating = true; @@ -100,6 +103,8 @@ public function toggleWorker(string $agentId): void public function save(CreateCrewAction $action): void { + Gate::authorize('edit-content'); + $this->validate(); try { diff --git a/app/Livewire/Crews/CrewDetailPage.php b/app/Livewire/Crews/CrewDetailPage.php index 5c8ff049..30cf54ce 100644 --- a/app/Livewire/Crews/CrewDetailPage.php +++ b/app/Livewire/Crews/CrewDetailPage.php @@ -9,6 +9,7 @@ use App\Domain\Crew\Enums\CrewStatus; use App\Domain\Crew\Models\Crew; use App\Domain\Crew\Models\CrewMember; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class CrewDetailPage extends Component @@ -59,6 +60,8 @@ public function mount(Crew $crew): void public function toggleStatus(): void { + Gate::authorize('edit-content'); + $newStatus = $this->crew->status === CrewStatus::Active ? CrewStatus::Archived : CrewStatus::Active; @@ -69,6 +72,8 @@ public function toggleStatus(): void public function activate(): void { + Gate::authorize('edit-content'); + $this->crew->update(['status' => CrewStatus::Active]); $this->crew->refresh(); } @@ -134,6 +139,8 @@ public function startEditMemberPolicy(string $memberId): void */ public function saveMemberPolicy(UpdateCrewAction $action): void { + Gate::authorize('edit-content'); + $this->validate([ 'editMemberMaxSteps' => 'nullable|integer|min:1|max:100', 'editMemberMaxCredits' => 'nullable|integer|min:1|max:1000000', @@ -168,6 +175,8 @@ public function cancelMemberPolicy(): void public function save(UpdateCrewAction $action): void { + Gate::authorize('edit-content'); + $teamId = auth()->user()->current_team_id; $this->validate([ @@ -203,6 +212,8 @@ public function save(UpdateCrewAction $action): void public function deleteCrew(): void { + Gate::authorize('edit-content'); + $this->crew->delete(); session()->flash('message', 'Crew deleted.'); $this->redirect(route('crews.index')); diff --git a/app/Livewire/Email/EmailTemplateBuilderPage.php b/app/Livewire/Email/EmailTemplateBuilderPage.php index 9cf66d3a..b06f91ef 100644 --- a/app/Livewire/Email/EmailTemplateBuilderPage.php +++ b/app/Livewire/Email/EmailTemplateBuilderPage.php @@ -9,6 +9,7 @@ use App\Domain\Email\Enums\EmailTemplateVisibility; use App\Domain\Email\Models\EmailTemplate; use App\Domain\Email\Models\EmailTheme; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class EmailTemplateBuilderPage extends Component @@ -43,6 +44,8 @@ public function mount(EmailTemplate $template): void public function saveSettings(): void { + Gate::authorize('edit-content'); + $this->validate([ 'name' => 'required|min:2|max:255', 'subject' => 'nullable|max:500', @@ -67,6 +70,8 @@ public function saveSettings(): void public function save(string $html, string $designJsonStr): void { + Gate::authorize('edit-content'); + $designJson = json_decode($designJsonStr, true) ?? []; app(RenderEmailTemplateAction::class)->execute($this->template, $html, $designJson); @@ -79,6 +84,8 @@ public function save(string $html, string $designJsonStr): void public function deleteTemplate(): void { + Gate::authorize('edit-content'); + app(DeleteEmailTemplateAction::class)->execute($this->template); session()->flash('message', 'Template deleted.'); diff --git a/app/Livewire/Email/EmailThemeDetailPage.php b/app/Livewire/Email/EmailThemeDetailPage.php index 8fe0361e..4bb9b73a 100644 --- a/app/Livewire/Email/EmailThemeDetailPage.php +++ b/app/Livewire/Email/EmailThemeDetailPage.php @@ -7,6 +7,7 @@ use App\Domain\Email\Enums\EmailThemeStatus; use App\Domain\Email\Models\EmailTheme; use App\Domain\Shared\Models\Team; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class EmailThemeDetailPage extends Component @@ -100,6 +101,8 @@ public function cancelEdit(): void public function save(): void { + Gate::authorize('edit-content'); + $this->validate([ 'editName' => 'required|min:2|max:255', 'editStatus' => 'required|in:draft,active,archived', @@ -158,6 +161,8 @@ public function save(): void public function setAsDefault(): void { + Gate::authorize('edit-content'); + $team = auth()->user()->currentTeam; Team::withoutGlobalScopes() @@ -169,6 +174,8 @@ public function setAsDefault(): void public function deleteTheme(): void { + Gate::authorize('edit-content'); + app(DeleteEmailThemeAction::class)->execute($this->theme); session()->flash('message', 'Email theme deleted.'); diff --git a/app/Livewire/GitRepositories/CreateGitRepositoryForm.php b/app/Livewire/GitRepositories/CreateGitRepositoryForm.php index 3429d316..e5170222 100644 --- a/app/Livewire/GitRepositories/CreateGitRepositoryForm.php +++ b/app/Livewire/GitRepositories/CreateGitRepositoryForm.php @@ -6,6 +6,7 @@ use App\Domain\GitRepository\Actions\CreateGitRepositoryAction; use App\Domain\GitRepository\Enums\GitProvider; use App\Domain\GitRepository\Enums\GitRepoMode; +use Illuminate\Support\Facades\Gate; use Illuminate\Validation\Rule; use Livewire\Component; @@ -79,6 +80,8 @@ public function prevStep(): void public function save(): void { + Gate::authorize('edit-content'); + $this->validate([ 'name' => 'required|min:2|max:255', 'url' => 'required|max:2048', diff --git a/app/Livewire/Integrations/IntegrationDetailPage.php b/app/Livewire/Integrations/IntegrationDetailPage.php index d1af062e..c671de35 100644 --- a/app/Livewire/Integrations/IntegrationDetailPage.php +++ b/app/Livewire/Integrations/IntegrationDetailPage.php @@ -12,6 +12,7 @@ use App\Domain\Tool\Enums\ToolStatus; use App\Domain\Tool\Models\Tool; use Carbon\Carbon; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class IntegrationDetailPage extends Component @@ -75,6 +76,8 @@ public function reconnect(OAuthConnectAction $action): mixed public function disconnect(DisconnectIntegrationAction $action): void { + Gate::authorize('edit-content'); + $action->execute($this->integration); session()->flash('message', 'Integration disconnected.'); $this->redirect(route('integrations.index'), navigate: true); @@ -85,6 +88,8 @@ public function disconnect(DisconnectIntegrationAction $action): void */ public function syncNow(SyncActivepiecesToolsAction $action): void { + Gate::authorize('edit-content'); + if ($this->integration->getAttribute('driver') !== 'activepieces') { return; } diff --git a/app/Livewire/Integrations/IntegrationListPage.php b/app/Livewire/Integrations/IntegrationListPage.php index 21b257ac..9361ccfc 100644 --- a/app/Livewire/Integrations/IntegrationListPage.php +++ b/app/Livewire/Integrations/IntegrationListPage.php @@ -8,6 +8,7 @@ use App\Domain\Integration\Actions\PingIntegrationAction; use App\Domain\Integration\Models\Integration; use App\Domain\Integration\Services\IntegrationManager; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class IntegrationListPage extends Component @@ -78,6 +79,8 @@ public function closeConnectForm(): void public function connectOAuth(OAuthConnectAction $action): mixed { + Gate::authorize('edit-content'); + $this->validate([ 'connectDriver' => 'required|string', 'connectName' => 'required|string|min:2|max:255', @@ -124,6 +127,8 @@ public function removeCredential(string $key): void public function connect(ConnectIntegrationAction $action): void { + Gate::authorize('edit-content'); + $this->validate([ 'connectDriver' => 'required|string', 'connectName' => 'required|string|min:2|max:255', @@ -150,6 +155,8 @@ public function connect(ConnectIntegrationAction $action): void public function disconnect(string $integrationId, DisconnectIntegrationAction $action): void { + Gate::authorize('edit-content'); + $integration = Integration::findOrFail($integrationId); $action->execute($integration); diff --git a/app/Livewire/OutboundConnectors/NotificationOutboundPage.php b/app/Livewire/OutboundConnectors/NotificationOutboundPage.php index 23a6f649..ef3fb8de 100644 --- a/app/Livewire/OutboundConnectors/NotificationOutboundPage.php +++ b/app/Livewire/OutboundConnectors/NotificationOutboundPage.php @@ -3,6 +3,7 @@ namespace App\Livewire\OutboundConnectors; use App\Domain\Outbound\Models\OutboundConnectorConfig; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class NotificationOutboundPage extends Component @@ -30,6 +31,8 @@ public function mount(): void public function save(): void { + Gate::authorize('manage-team'); + $this->validate([ 'defaultPriority' => 'required|in:low,normal,high', ]); diff --git a/app/Livewire/OutboundConnectors/OutboundConnectorsPage.php b/app/Livewire/OutboundConnectors/OutboundConnectorsPage.php index 7e45b464..d3e3bb24 100644 --- a/app/Livewire/OutboundConnectors/OutboundConnectorsPage.php +++ b/app/Livewire/OutboundConnectors/OutboundConnectorsPage.php @@ -4,6 +4,7 @@ use App\Domain\Email\Models\EmailTemplate; use App\Domain\Outbound\Models\OutboundConnectorConfig; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class OutboundConnectorsPage extends Component @@ -66,6 +67,8 @@ public function mount(): void public function save(): void { + Gate::authorize('manage-team'); + $this->validate([ 'host' => 'required|string|max:255', 'port' => 'required|integer|between:1,65535', @@ -116,6 +119,8 @@ public function save(): void public function testConnection(): void { + Gate::authorize('manage-team'); + $team = auth()->user()->currentTeam; $config = OutboundConnectorConfig::where('team_id', $team->id) ->where('channel', 'email') diff --git a/app/Livewire/OutboundConnectors/WebhookOutboundPage.php b/app/Livewire/OutboundConnectors/WebhookOutboundPage.php index a218cd7b..d83ea5d7 100644 --- a/app/Livewire/OutboundConnectors/WebhookOutboundPage.php +++ b/app/Livewire/OutboundConnectors/WebhookOutboundPage.php @@ -3,6 +3,7 @@ namespace App\Livewire\OutboundConnectors; use App\Domain\Outbound\Models\OutboundConnectorConfig; +use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Http; use Livewire\Component; @@ -46,6 +47,8 @@ public function mount(): void public function save(): void { + Gate::authorize('manage-team'); + $this->validate([ 'webhookUrl' => 'required|url|max:2048', 'method' => 'required|in:POST,PUT,PATCH', @@ -84,6 +87,8 @@ public function save(): void public function testConnection(): void { + Gate::authorize('manage-team'); + $team = auth()->user()->currentTeam; $config = OutboundConnectorConfig::where('team_id', $team->id) ->where('channel', 'webhook') diff --git a/app/Livewire/OutboundConnectors/WhatsAppOutboundPage.php b/app/Livewire/OutboundConnectors/WhatsAppOutboundPage.php index cd2f9cb4..b1fb5ae9 100644 --- a/app/Livewire/OutboundConnectors/WhatsAppOutboundPage.php +++ b/app/Livewire/OutboundConnectors/WhatsAppOutboundPage.php @@ -4,6 +4,7 @@ use App\Domain\Outbound\Models\OutboundConnectorConfig; use Illuminate\Contracts\View\View; +use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Http; use Livewire\Component; @@ -59,6 +60,8 @@ public function mount(): void public function save(): void { + Gate::authorize('manage-team'); + $this->validate([ 'phoneNumberId' => 'required|string|max:64|regex:/^\d+$/', 'businessAccountId' => 'nullable|string|max:64', @@ -104,6 +107,8 @@ public function save(): void */ public function testConnection(): void { + Gate::authorize('manage-team'); + $team = auth()->user()->currentTeam; $config = OutboundConnectorConfig::where('team_id', $team->id) ->where('channel', 'whatsapp') diff --git a/app/Livewire/Projects/CreateProjectForm.php b/app/Livewire/Projects/CreateProjectForm.php index 6286c689..e3f471c1 100644 --- a/app/Livewire/Projects/CreateProjectForm.php +++ b/app/Livewire/Projects/CreateProjectForm.php @@ -12,6 +12,7 @@ use App\Domain\Tool\Models\Tool; use App\Domain\Workflow\Enums\WorkflowStatus; use App\Domain\Workflow\Models\Workflow; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class CreateProjectForm extends Component @@ -136,6 +137,8 @@ public function updatedDependencies($value, $key): void public function save(): void { + Gate::authorize('edit-content'); + $this->validate(); $team = auth()->user()->currentTeam; diff --git a/app/Livewire/Projects/ProjectDetailPage.php b/app/Livewire/Projects/ProjectDetailPage.php index 0d1c3391..f7181bd9 100644 --- a/app/Livewire/Projects/ProjectDetailPage.php +++ b/app/Livewire/Projects/ProjectDetailPage.php @@ -15,6 +15,7 @@ use App\Domain\Project\Models\ProjectMilestone; use App\Domain\Project\Models\ProjectRun; use App\Domain\Tool\Models\Tool; +use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\RateLimiter; use Livewire\Component; @@ -31,6 +32,8 @@ public function mount(Project $project): void public function pause(): void { + Gate::authorize('edit-content'); + app(PauseProjectAction::class)->execute($this->project, 'Manually paused'); $this->project->refresh(); session()->flash('message', 'Project paused.'); @@ -38,6 +41,8 @@ public function pause(): void public function resume(): void { + Gate::authorize('edit-content'); + app(ResumeProjectAction::class)->execute($this->project); $this->project->refresh(); session()->flash('message', 'Project resumed.'); @@ -45,6 +50,8 @@ public function resume(): void public function archive(): void { + Gate::authorize('edit-content'); + app(ArchiveProjectAction::class)->execute($this->project); $this->project->refresh(); session()->flash('message', 'Project archived.'); @@ -52,6 +59,8 @@ public function archive(): void public function activate(): void { + Gate::authorize('edit-content'); + if ($this->project->status !== ProjectStatus::Draft) { return; } @@ -75,6 +84,8 @@ public function activate(): void public function restart(): void { + Gate::authorize('edit-content'); + app(RestartProjectAction::class)->execute($this->project); $this->project->refresh(); session()->flash('message', 'Project restarted from scratch. New run triggered.'); @@ -82,6 +93,8 @@ public function restart(): void public function triggerRun(): void { + Gate::authorize('edit-content'); + $key = 'trigger-run:'.$this->project->id; if (RateLimiter::tooManyAttempts($key, 3)) { diff --git a/app/Livewire/Settings/ConnectorConfigModal.php b/app/Livewire/Settings/ConnectorConfigModal.php index c260b117..6e2f9dc6 100644 --- a/app/Livewire/Settings/ConnectorConfigModal.php +++ b/app/Livewire/Settings/ConnectorConfigModal.php @@ -4,6 +4,7 @@ use App\Domain\Outbound\Models\OutboundConnectorConfig; use App\Domain\Outbound\Services\OutboundCredentialResolver; +use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Http; use Livewire\Attributes\On; use Livewire\Component; @@ -114,6 +115,8 @@ public function openModal(string $channel): void public function save(): void { + Gate::authorize('manage-team'); + $credentials = $this->collectCredentials(); if (empty(array_filter($credentials, fn ($v) => $v !== null && $v !== ''))) { @@ -138,6 +141,8 @@ public function save(): void public function testConnection(): void { + Gate::authorize('manage-team'); + $this->testing = true; $this->testResult = null; $this->testError = null; @@ -169,6 +174,8 @@ public function testConnection(): void public function disconnect(): void { + Gate::authorize('manage-team'); + $teamId = $this->resolveTeamId(); OutboundConnectorConfig::withoutGlobalScopes() diff --git a/app/Livewire/Settings/WebhookSettingsPanel.php b/app/Livewire/Settings/WebhookSettingsPanel.php index ad563187..7d3d0677 100644 --- a/app/Livewire/Settings/WebhookSettingsPanel.php +++ b/app/Livewire/Settings/WebhookSettingsPanel.php @@ -6,6 +6,7 @@ use App\Domain\Webhook\Enums\WebhookEvent; use App\Domain\Webhook\Models\WebhookEndpoint; use App\Models\User; +use Illuminate\Support\Facades\Gate; use Illuminate\Support\Str; use Livewire\Component; @@ -60,6 +61,8 @@ public function openForm(?string $id = null): void public function save(): void { + Gate::authorize('manage-team'); + $this->validate(); /** @var User $user */ @@ -95,6 +98,8 @@ public function save(): void public function toggleActive(string $id): void { + Gate::authorize('manage-team'); + $endpoint = WebhookEndpoint::find($id); if ($endpoint) { $endpoint->update(['is_active' => ! $endpoint->is_active]); @@ -103,6 +108,8 @@ public function toggleActive(string $id): void public function delete(string $id): void { + Gate::authorize('manage-team'); + WebhookEndpoint::find($id)?->delete(); } diff --git a/app/Livewire/Signals/ConnectorSetupPanel.php b/app/Livewire/Signals/ConnectorSetupPanel.php index e1bd416c..847a3919 100644 --- a/app/Livewire/Signals/ConnectorSetupPanel.php +++ b/app/Livewire/Signals/ConnectorSetupPanel.php @@ -6,6 +6,7 @@ use App\Domain\Signal\Actions\RotateSignalSecretAction; use App\Domain\Signal\Models\Signal; use App\Domain\Signal\Models\SignalConnectorSetting; +use Illuminate\Support\Facades\Gate; use Livewire\Attributes\On; use Livewire\Component; @@ -203,6 +204,8 @@ public function cancelRotate(): void */ public function rotateSecret(): void { + Gate::authorize('manage-team'); + $teamId = auth()->user()?->currentTeam?->id ?? session('team_id'); if (! $teamId) { @@ -231,6 +234,8 @@ public function rotateSecret(): void */ public function savePastedSecret(): void { + Gate::authorize('manage-team'); + $this->validate(['pasteSecretValue' => 'required|min:8']); $teamId = auth()->user()?->currentTeam?->id ?? session('team_id'); diff --git a/app/Livewire/Skills/CreateSkillForm.php b/app/Livewire/Skills/CreateSkillForm.php index 0af907f2..7b5ea731 100644 --- a/app/Livewire/Skills/CreateSkillForm.php +++ b/app/Livewire/Skills/CreateSkillForm.php @@ -186,6 +186,8 @@ public function removeConsensusModel(int $index): void public function save(): void { + Gate::authorize('edit-content'); + $allowedTypes = 'llm,connector,rule,hybrid,guardrail,multi_model_consensus,code_execution,gpu_compute,runpod_endpoint,runpod_pod,boruna_script,supabase_edge_function'; if (config('browser.enabled', false)) { $allowedTypes .= ',browser'; diff --git a/app/Livewire/Skills/SkillDetailPage.php b/app/Livewire/Skills/SkillDetailPage.php index d508e5b9..2b0f1732 100644 --- a/app/Livewire/Skills/SkillDetailPage.php +++ b/app/Livewire/Skills/SkillDetailPage.php @@ -15,6 +15,7 @@ use App\Domain\Skill\Models\SkillExecution; use App\Domain\Skill\Models\SkillVersion; use App\Infrastructure\AI\Services\ProviderResolver; +use Illuminate\Support\Facades\Gate; use Livewire\Attributes\On; use Livewire\Component; @@ -69,6 +70,8 @@ public function mount(Skill $skill): void public function toggleStatus(): void { + Gate::authorize('edit-content'); + $newStatus = $this->skill->status === SkillStatus::Active ? SkillStatus::Disabled : SkillStatus::Active; @@ -100,6 +103,8 @@ public function cancelEdit(): void public function save(): void { + Gate::authorize('edit-content'); + $this->validate([ 'editName' => 'required|min:2|max:255', 'editDescription' => 'max:1000', @@ -136,6 +141,8 @@ public function save(): void public function deleteSkill(): void { + Gate::authorize('edit-content'); + $this->skill->delete(); session()->flash('message', 'Skill deleted.'); @@ -144,6 +151,8 @@ public function deleteSkill(): void public function startBenchmark(): void { + Gate::authorize('edit-content'); + $this->validate([ 'benchMetricName' => 'required|string|max:100', 'benchMetricDirection' => 'required|in:maximize,minimize', diff --git a/app/Livewire/Telegram/TelegramBotsPage.php b/app/Livewire/Telegram/TelegramBotsPage.php index c6687d86..ae13bcf4 100644 --- a/app/Livewire/Telegram/TelegramBotsPage.php +++ b/app/Livewire/Telegram/TelegramBotsPage.php @@ -5,6 +5,7 @@ use App\Domain\Project\Models\Project; use App\Domain\Telegram\Actions\RegisterTelegramBotAction; use App\Domain\Telegram\Models\TelegramBot; +use Illuminate\Support\Facades\Gate; use Illuminate\Validation\ValidationException; use Livewire\Component; @@ -35,6 +36,8 @@ public function rules(): array public function save(): void { + Gate::authorize('edit-content'); + $this->validate(); $this->error = null; @@ -60,6 +63,8 @@ public function save(): void public function toggleStatus(string $botId): void { + Gate::authorize('edit-content'); + $bot = TelegramBot::findOrFail($botId); $bot->update(['status' => $bot->isActive() ? 'disabled' : 'active']); $this->success = 'Bot status updated.'; @@ -68,6 +73,8 @@ public function toggleStatus(string $botId): void public function delete(string $botId): void { + Gate::authorize('edit-content'); + TelegramBot::findOrFail($botId)->delete(); $this->success = 'Bot removed.'; $this->error = null; diff --git a/app/Livewire/Tools/CreateToolForm.php b/app/Livewire/Tools/CreateToolForm.php index f066a015..a848c011 100644 --- a/app/Livewire/Tools/CreateToolForm.php +++ b/app/Livewire/Tools/CreateToolForm.php @@ -9,6 +9,7 @@ use App\Domain\Tool\Enums\BuiltInToolKind; use App\Domain\Tool\Enums\ToolRiskLevel; use App\Domain\Tool\Enums\ToolType; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class CreateToolForm extends Component @@ -132,6 +133,8 @@ private function validateTransportConfig(): void public function save(): void { + Gate::authorize('edit-content'); + $team = auth()->user()->currentTeam; $type = ToolType::from($this->type); diff --git a/app/Livewire/Tools/ToolDetailPage.php b/app/Livewire/Tools/ToolDetailPage.php index c431953c..1c7eb267 100644 --- a/app/Livewire/Tools/ToolDetailPage.php +++ b/app/Livewire/Tools/ToolDetailPage.php @@ -12,6 +12,7 @@ use App\Domain\Tool\Enums\ToolStatus; use App\Domain\Tool\Models\TeamToolActivation; use App\Domain\Tool\Models\Tool; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class ToolDetailPage extends Component @@ -61,6 +62,8 @@ protected function initCredentialInputs(): void public function toggleStatus(): void { + Gate::authorize('edit-content'); + $teamId = auth()->user()->current_team_id; if ($this->tool->isPlatformTool()) { @@ -84,6 +87,8 @@ public function toggleStatus(): void public function saveCredentials(): void { + Gate::authorize('edit-content'); + $teamId = auth()->user()->current_team_id; $overrides = array_filter($this->credentialInputs, fn ($v) => $v !== ''); @@ -121,6 +126,8 @@ public function cancelEdit(): void public function save(): void { + Gate::authorize('edit-content'); + if ($this->tool->isPlatformTool()) { return; } @@ -147,6 +154,8 @@ public function save(): void public function saveProxyCredential(): void { + Gate::authorize('edit-content'); + $config = $this->tool->transport_config ?? []; if ($this->proxyCredentialId) { @@ -166,6 +175,8 @@ public function saveProxyCredential(): void public function deleteTool(): void { + Gate::authorize('edit-content'); + if ($this->tool->isPlatformTool()) { return; } diff --git a/app/Livewire/Toolsets/CreateToolsetForm.php b/app/Livewire/Toolsets/CreateToolsetForm.php index 279eaa3a..f8a30a13 100644 --- a/app/Livewire/Toolsets/CreateToolsetForm.php +++ b/app/Livewire/Toolsets/CreateToolsetForm.php @@ -5,6 +5,7 @@ use App\Domain\Tool\Actions\CreateToolsetAction; use App\Domain\Tool\Enums\ToolStatus; use App\Domain\Tool\Models\Tool; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class CreateToolsetForm extends Component @@ -31,6 +32,8 @@ protected function rules(): array public function save(): void { + Gate::authorize('edit-content'); + $this->validate(); $teamId = auth()->user()->current_team_id; diff --git a/app/Livewire/Toolsets/ToolsetDetailPage.php b/app/Livewire/Toolsets/ToolsetDetailPage.php index f8a4bb04..a68c3067 100644 --- a/app/Livewire/Toolsets/ToolsetDetailPage.php +++ b/app/Livewire/Toolsets/ToolsetDetailPage.php @@ -7,6 +7,7 @@ use App\Domain\Tool\Enums\ToolStatus; use App\Domain\Tool\Models\Tool; use App\Domain\Tool\Models\Toolset; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class ToolsetDetailPage extends Component @@ -42,6 +43,8 @@ public function cancelEdit(): void public function save(): void { + Gate::authorize('edit-content'); + $teamId = auth()->user()->current_team_id; $this->validate([ @@ -67,6 +70,8 @@ public function save(): void public function delete(): void { + Gate::authorize('edit-content'); + app(DeleteToolsetAction::class)->execute($this->toolset); $this->redirect(route('toolsets.index'), navigate: true); } diff --git a/app/Livewire/Triggers/CreateTriggerRuleForm.php b/app/Livewire/Triggers/CreateTriggerRuleForm.php index fcff5edc..2052449c 100644 --- a/app/Livewire/Triggers/CreateTriggerRuleForm.php +++ b/app/Livewire/Triggers/CreateTriggerRuleForm.php @@ -4,6 +4,7 @@ use App\Domain\Project\Models\Project; use App\Domain\Trigger\Actions\CreateTriggerRuleAction; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class CreateTriggerRuleForm extends Component @@ -57,6 +58,8 @@ public function removeMappingRow(int $index): void public function save(CreateTriggerRuleAction $action): void { + Gate::authorize('edit-content'); + $teamId = auth()->user()->current_team_id; $this->validate([ diff --git a/app/Livewire/Triggers/TriggerRulesPage.php b/app/Livewire/Triggers/TriggerRulesPage.php index 4314901d..f2448ceb 100644 --- a/app/Livewire/Triggers/TriggerRulesPage.php +++ b/app/Livewire/Triggers/TriggerRulesPage.php @@ -8,6 +8,7 @@ use App\Domain\Trigger\Actions\ExecuteTriggerRuleAction; use App\Domain\Trigger\Actions\UpdateTriggerRuleAction; use App\Domain\Trigger\Models\TriggerRule; +use Illuminate\Support\Facades\Gate; use Livewire\Component; use Livewire\WithPagination; @@ -59,6 +60,8 @@ public function cancelEdit(): void public function saveEdit(): void { + Gate::authorize('edit-content'); + $teamId = auth()->user()->current_team_id; $this->validate([ @@ -85,6 +88,8 @@ public function saveEdit(): void public function testTrigger(string $ruleId): void { + Gate::authorize('edit-content'); + $rule = TriggerRule::findOrFail($ruleId); // Find the most recent matching signal, or create a test one @@ -114,6 +119,8 @@ public function testTrigger(string $ruleId): void public function toggleStatus(string $ruleId): void { + Gate::authorize('edit-content'); + $rule = TriggerRule::findOrFail($ruleId); $newStatus = $rule->status->isActive() ? 'paused' : 'active'; @@ -124,6 +131,8 @@ public function toggleStatus(string $ruleId): void public function delete(string $ruleId): void { + Gate::authorize('edit-content'); + $rule = TriggerRule::findOrFail($ruleId); app(DeleteTriggerRuleAction::class)->execute($rule); diff --git a/app/Livewire/Websites/WebsiteBuilderPage.php b/app/Livewire/Websites/WebsiteBuilderPage.php index a6886c3b..28d72a26 100644 --- a/app/Livewire/Websites/WebsiteBuilderPage.php +++ b/app/Livewire/Websites/WebsiteBuilderPage.php @@ -6,6 +6,7 @@ use App\Domain\Website\Actions\UpdateWebsitePageAction; use App\Domain\Website\Models\Website; use App\Domain\Website\Models\WebsitePage; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class WebsiteBuilderPage extends Component @@ -33,6 +34,8 @@ public function mount(Website $website, WebsitePage $page): void public function saveContent(array $grapesJson, string $html, string $css): void { + Gate::authorize('edit-content'); + app(UpdateWebsitePageAction::class)->execute($this->page, [ 'grapes_json' => $grapesJson, 'exported_html' => $html, @@ -44,6 +47,8 @@ public function saveContent(array $grapesJson, string $html, string $css): void public function saveSettings(): void { + Gate::authorize('edit-content'); + $this->validate([ 'title' => 'required|max:255', 'slug' => 'required|max:255', @@ -60,6 +65,8 @@ public function saveSettings(): void public function publishPage(): void { + Gate::authorize('edit-content'); + app(PublishWebsitePageAction::class)->execute($this->page); session()->flash('message', 'Page published.'); diff --git a/app/Livewire/Websites/WebsiteDetailPage.php b/app/Livewire/Websites/WebsiteDetailPage.php index 86e927b7..7125a84b 100644 --- a/app/Livewire/Websites/WebsiteDetailPage.php +++ b/app/Livewire/Websites/WebsiteDetailPage.php @@ -15,6 +15,7 @@ use App\Domain\Website\Exceptions\DeploymentDriverException; use App\Domain\Website\Models\Website; use App\Domain\Website\Models\WebsitePage; +use Illuminate\Support\Facades\Gate; use Illuminate\Support\Str; use Livewire\Component; @@ -42,6 +43,8 @@ public function updatedPageTitle(): void public function addPage(): void { + Gate::authorize('edit-content'); + $this->validate([ 'pageTitle' => 'required|max:255', 'pageSlug' => 'required|max:255', @@ -64,6 +67,8 @@ public function addPage(): void public function deletePage(string $pageId): void { + Gate::authorize('edit-content'); + // Scope to this website — prevents cross-website page deletion within same team $page = $this->website->pages()->findOrFail($pageId); app(DeleteWebsitePageAction::class)->execute($page); @@ -74,6 +79,8 @@ public function deletePage(string $pageId): void public function publishPage(string $pageId): void { + Gate::authorize('edit-content'); + // Scope to this website — prevents cross-website page publishing within same team $page = $this->website->pages()->findOrFail($pageId); app(PublishWebsitePageAction::class)->execute($page); @@ -84,6 +91,8 @@ public function publishPage(string $pageId): void public function unpublishPage(string $pageId): void { + Gate::authorize('edit-content'); + // Scope to this website — prevents cross-website page unpublishing within same team $page = $this->website->pages()->findOrFail($pageId); app(UnpublishWebsitePageAction::class)->execute($page); @@ -94,6 +103,8 @@ public function unpublishPage(string $pageId): void public function unpublishWebsite(): void { + Gate::authorize('edit-content'); + app(UnpublishWebsiteAction::class)->execute($this->website); session()->flash('success', 'Website unpublished.'); @@ -102,6 +113,8 @@ public function unpublishWebsite(): void public function publishWebsite(): void { + Gate::authorize('edit-content'); + // Only publish draft pages that have content — skip empty drafts $this->website->pages() ->where('status', 'draft') @@ -119,6 +132,8 @@ public function publishWebsite(): void public function deleteWebsite(): void { + Gate::authorize('edit-content'); + app(DeleteWebsiteAction::class)->execute($this->website); session()->flash('success', 'Website deleted.'); @@ -127,6 +142,8 @@ public function deleteWebsite(): void public function deployWebsite(string $provider = 'zip'): void { + Gate::authorize('edit-content'); + $providerEnum = DeploymentProvider::tryFrom($provider); if (! $providerEnum) { session()->flash('error', "Unknown deployment provider '{$provider}'."); diff --git a/app/Livewire/Workflows/ScheduleWorkflowForm.php b/app/Livewire/Workflows/ScheduleWorkflowForm.php index a211d4b1..1689d484 100644 --- a/app/Livewire/Workflows/ScheduleWorkflowForm.php +++ b/app/Livewire/Workflows/ScheduleWorkflowForm.php @@ -10,6 +10,7 @@ use App\Domain\Project\Services\NaturalLanguageScheduleParser; use App\Domain\Workflow\Enums\WorkflowStatus; use App\Domain\Workflow\Models\Workflow; +use Illuminate\Support\Facades\Gate; use Livewire\Component; class ScheduleWorkflowForm extends Component @@ -131,6 +132,8 @@ public function parseNlpSchedule(): void public function save(): void { + Gate::authorize('edit-content'); + if ($this->useNlpSchedule && $this->nlpScheduleInput) { $this->parseNlpSchedule(); } diff --git a/app/Livewire/Workflows/WorkflowBuilderPage.php b/app/Livewire/Workflows/WorkflowBuilderPage.php index 6c03d0eb..4f48cece 100644 --- a/app/Livewire/Workflows/WorkflowBuilderPage.php +++ b/app/Livewire/Workflows/WorkflowBuilderPage.php @@ -15,6 +15,7 @@ use App\Domain\Workflow\Actions\ValidateWorkflowGraphAction; use App\Domain\Workflow\Enums\WorkflowNodeType; use App\Domain\Workflow\Models\Workflow; +use Illuminate\Support\Facades\Gate; use Livewire\Attributes\On; use Livewire\Component; @@ -164,12 +165,16 @@ public function mount(?Workflow $workflow = null): void public function saveGraph(array $nodes, array $edges): void { + Gate::authorize('edit-content'); + $this->nodes = $nodes; $this->edges = $edges; } public function save(bool $flash = true): void { + Gate::authorize('edit-content'); + $this->validate([ 'name' => 'required|string|max:255', 'maxLoopIterations' => 'required|integer|min:1|max:100',