added a help system, replaced the words "tenant" and "Pwa" with better alternatives. corrected and implemented cron jobs. prepared going live on a coolify-powered system.
This commit is contained in:
129
app/Http/Controllers/Api/HelpController.php
Normal file
129
app/Http/Controllers/Api/HelpController.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Support\Help\HelpRepository;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Sanctum\PersonalAccessToken;
|
||||
use RuntimeException;
|
||||
|
||||
class HelpController extends Controller
|
||||
{
|
||||
public function __construct(private readonly HelpRepository $repository) {}
|
||||
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
[$audience, $locale] = $this->resolveContext($request);
|
||||
|
||||
$articles = $this->getArticles($audience, $locale)
|
||||
->map(fn ($article) => Arr::only($article, config('help.list_fields')))
|
||||
->values();
|
||||
|
||||
return response()->json([
|
||||
'data' => $articles,
|
||||
]);
|
||||
}
|
||||
|
||||
public function show(Request $request, string $slug): JsonResponse
|
||||
{
|
||||
[$audience, $locale] = $this->resolveContext($request);
|
||||
|
||||
$article = $this->getArticle($audience, $locale, $slug);
|
||||
|
||||
abort_if(! $article, 404, 'Help article not found.');
|
||||
|
||||
return response()->json([
|
||||
'data' => $article,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{string, string}
|
||||
*/
|
||||
private function resolveContext(Request $request): array
|
||||
{
|
||||
$this->attemptTokenAuthentication($request);
|
||||
|
||||
$audience = Str::of($request->string('audience', 'guest'))->lower()->value();
|
||||
$locale = Str::of($request->string('locale', config('help.default_locale')))->lower()->value();
|
||||
|
||||
if ($audience === 'admin' && ! $request->user()) {
|
||||
abort(401, 'Authentication required for admin help content.');
|
||||
}
|
||||
|
||||
if (! in_array($audience, config('help.audiences', []), true)) {
|
||||
abort(400, 'Invalid audience supplied.');
|
||||
}
|
||||
|
||||
return [$audience, $locale];
|
||||
}
|
||||
|
||||
private function attemptTokenAuthentication(Request $request): void
|
||||
{
|
||||
if ($request->user()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$bearer = $request->bearerToken();
|
||||
|
||||
if (! $bearer) {
|
||||
return;
|
||||
}
|
||||
|
||||
$token = PersonalAccessToken::findToken($bearer);
|
||||
|
||||
if (! $token) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = $token->tokenable;
|
||||
|
||||
if (! $user) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (method_exists($user, 'withAccessToken')) {
|
||||
$user->withAccessToken($token);
|
||||
}
|
||||
|
||||
Auth::setUser($user);
|
||||
$request->setUserResolver(fn () => $user);
|
||||
}
|
||||
|
||||
private function getArticles(string $audience, string $locale)
|
||||
{
|
||||
try {
|
||||
return $this->repository->list($audience, $locale);
|
||||
} catch (RuntimeException $e) {
|
||||
$fallback = config('help.fallback_locale');
|
||||
|
||||
if ($locale === $fallback) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $this->repository->list($audience, $fallback);
|
||||
}
|
||||
}
|
||||
|
||||
private function getArticle(string $audience, string $locale, string $slug): ?array
|
||||
{
|
||||
try {
|
||||
$article = $this->repository->find($audience, $locale, $slug);
|
||||
} catch (RuntimeException $e) {
|
||||
$fallback = config('help.fallback_locale');
|
||||
|
||||
if ($locale !== $fallback) {
|
||||
return $this->repository->find($audience, $fallback, $slug);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $article;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user