exists(); if (!$hasAccess) { abort(403); } } private function requireManagerAccess(int $groupId): void { $isManager = TicketingAgentAccess::where('user_id', Auth::id()) ->where('group_id', $groupId) ->where('role', 'manager') ->exists(); if (!$isManager) { abort(403); } } public function index(): Response { $this->requireAgentAccess(); $userId = Auth::id(); $myGroupIds = TicketingAgentAccess::where('user_id', $userId)->pluck('group_id'); $groups = TicketingGroup::whereIn('id', $myGroupIds)->get(); $agents = TicketingAgentAccess::whereIn('group_id', $myGroupIds)->get(); $agentUserIds = $agents->pluck('user_id')->unique(); $agentUsers = \DB::table('users')->whereIn('id', $agentUserIds)->get(['id', 'name', 'email'])->keyBy('id'); $agents->each(fn($a) => $a->user = $agentUsers[$a->user_id] ?? null); $priorities = PriorityLevel::where(fn($q) => $q->whereNull('group_id')->orWhereIn('group_id', $myGroupIds)) ->orderBy('sort_order')->get(); return Inertia::render('Ticketing/Settings', [ 'groups' => $groups, 'agents' => $agents, 'priorities' => $priorities, 'myGroupIds' => $myGroupIds, ]); } public function storeGroup(Request $request) { $this->requireAgentAccess(); $validated = $request->validate([ 'name' => 'required|string|max:100', 'email_address' => 'nullable|email', 'color' => 'required|string|regex:/^#[0-9a-fA-F]{6}$/', 'prefix' => 'required|string|max:10|alpha_num|unique:ticketing_groups,prefix', ]); $group = TicketingGroup::create($validated); // Auto-add creator as manager TicketingAgentAccess::create([ 'user_id' => Auth::id(), 'group_id' => $group->id, 'role' => 'manager', ]); return back()->with('success', 'Group created.'); } public function updateGroup(Request $request, TicketingGroup $group) { $this->requireManagerAccess($group->id); $validated = $request->validate([ 'name' => 'required|string|max:100', 'email_address' => 'nullable|email', 'color' => 'required|string|regex:/^#[0-9a-fA-F]{6}$/', 'prefix' => 'required|string|max:10|alpha_num|unique:ticketing_groups,prefix,' . $group->id, ]); $group->update($validated); return back()->with('success', 'Group updated.'); } public function storeAgent(Request $request) { $this->requireAgentAccess(); $validated = $request->validate([ 'user_id' => 'required|exists:users,id', 'group_id' => 'required|exists:ticketing_groups,id', 'role' => 'required|in:agent,manager', ]); $this->requireManagerAccess($validated['group_id']); TicketingAgentAccess::updateOrCreate( ['user_id' => $validated['user_id'], 'group_id' => $validated['group_id']], ['role' => $validated['role']] ); return back()->with('success', 'Agent added.'); } public function destroyAgent(TicketingAgentAccess $access) { $this->requireManagerAccess($access->group_id); $access->delete(); return back()->with('success', 'Agent removed.'); } public function storePriority(Request $request) { $this->requireAgentAccess(); $validated = $request->validate([ 'name' => 'required|string|max:100', 'color' => 'required|string|regex:/^#[0-9a-fA-F]{6}$/', 'description' => 'nullable|string', 'sort_order' => 'integer|min:0', 'group_id' => 'nullable|exists:ticketing_groups,id', ]); PriorityLevel::create($validated); return back()->with('success', 'Priority level created.'); } }