guard($publicSlug, $file); return response()->json($this->presenter->thread($request->user(), $file)); } public function store(Request $request, string $publicSlug, File $file): JsonResponse { $this->guard($publicSlug, $file); $viewer = $request->user(); $validated = $request->validate([ 'body' => ['required', 'string', 'max:5000'], // A visitor has no account to take a name from, so they give // one. Ignored for a signed-in author, whose name is real. 'guest_name' => [$viewer === null ? 'required' : 'nullable', 'string', 'max:80'], // Accepted and ignored: the shared composer sends the whole // form, and a visitor's only possible visibility is Everyone. 'visibility' => ['nullable', 'string'], // Only a visitor is challenged — see CommentingRules. A signed // in viewer reaching this endpoint is served as themselves, and // proving they are human on a page that knows who they are // would be friction with nothing behind it. ...($this->rules->captchaRequiredFor($viewer) ? Rules::captcha(CaptchaForm::Comment) : []), ]); $comment = $this->comments->post( $file, $viewer, CommentVisibility::Everyone, $validated['body'], null, $validated['guest_name'] ?? null, ); // So a visitor keeps seeing their own comment while it waits. The // only place this is recorded, because it is the only place a // comment is written without an account. if ($viewer === null) { $this->guests->remember($comment->id); } return response()->json($this->presenter->thread($viewer, $file), 201); } /** * The file must be reachable without logging in, and the public * listing itself must be switched on — the same two conditions * PublicGroupsController applies before rendering the page this * endpoint belongs to. Commenting being configured off 404s rather * than returning an empty thread: the endpoint should not exist. */ private function guard(string $publicSlug, File $file): void { abort_unless($this->settings->get(Setting::PublicListingSlug) === $publicSlug, 404); abort_unless($file->isEffectivelyPublic() && ! $file->isExpired(), 404); abort_unless($this->rules->enabled(), 404); } }