user() ->projects() ->withCount(['issues' => fn ($q) => $q->where('status', 'unresolved')]) ->orderBy('name') ->get(); return view('projects.index', compact('projects')); } public function create(): View { return view('projects.create'); } public function store(Request $request): RedirectResponse { $validated = $request->validate([ 'name' => 'required|string|max:255', 'platform' => 'nullable|string|max:50', ]); $project = Project::create($validated); $request->user()->projects()->attach($project, ['role' => 'owner']); return redirect() ->route('projects.settings', $project) ->with('status', 'Project created. Here is your DSN.'); } public function settings(Request $request, Project $project): View { $this->authorizeProject($request, $project); return view('projects.settings', compact('project')); } public function update(Request $request, Project $project): RedirectResponse { $this->authorizeProject($request, $project); $validated = $request->validate([ 'name' => 'required|string|max:255', 'platform' => 'nullable|string|max:50', ]); $project->update($validated); return back()->with('status', 'Project updated.'); } public function regenerateKeys(Request $request, Project $project): RedirectResponse { $this->authorizeProject($request, $project); $project->regenerateKeys(); return back()->with('status', 'DSN keys regenerated.'); } public function destroy(Request $request, Project $project): RedirectResponse { $this->authorizeProject($request, $project); $project->delete(); return redirect()->route('projects.index')->with('status', 'Project deleted.'); } private function authorizeProject(Request $request, Project $project): void { abort_unless( $request->user()->projects()->where('projects.id', $project->id)->exists(), 403, ); } }