user(); // Rate limit: 10 post creations per hour $key = 'create_post:' . $user->id; if (RateLimiter::tooManyAttempts($key, 10)) { $seconds = RateLimiter::availableIn($key); return response()->json([ 'message' => "You're posting too quickly. Please wait {$seconds} seconds.", ], 429); } RateLimiter::hit($key, 3600); Gate::authorize('create', Post::class); $post = $this->postService->createPost( user: $user, type: $request->input('type', Post::TYPE_TEXT), visibility: $request->input('visibility', Post::VISIBILITY_PUBLIC), body: $request->input('body'), targets: $request->input('targets', []), linkPreview: $request->input('link_preview'), taggedUsers: $request->input('tagged_users'), publishAt: $request->filled('publish_at') ? Carbon::parse($request->input('publish_at')) : null, ); $post->load(['user', 'user.profile', 'targets', 'targets.artwork', 'targets.artwork.user', 'targets.artwork.user.profile', 'reactions']); return response()->json([ 'post' => $this->feedService->formatPost($post, $user->id), ], 201); } // ───────────────────────────────────────────────────────────────────────── // Update // ───────────────────────────────────────────────────────────────────────── public function update(UpdatePostRequest $request, int $id): JsonResponse { $post = Post::findOrFail($id); Gate::authorize('update', $post); $updated = $this->postService->updatePost( post: $post, body: $request->input('body'), visibility: $request->input('visibility'), ); return response()->json([ 'post' => $this->feedService->formatPost($updated->load(['user', 'user.profile', 'targets', 'targets.artwork', 'targets.artwork.user', 'targets.artwork.user.profile', 'reactions']), $request->user()?->id), ]); } // ───────────────────────────────────────────────────────────────────────── // Delete // ───────────────────────────────────────────────────────────────────────── public function destroy(int $id): JsonResponse { $post = Post::findOrFail($id); Gate::authorize('delete', $post); $this->postService->deletePost($post); return response()->json(['message' => 'Post deleted.']); } }