GeoNetAgent, LDAPWeb, server-audit, server-connection
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

120 lines
4.1 KiB

<?php
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Api\Concerns\RespondsWithJson;
use App\Http\Controllers\Controller;
use App\Models\Feedback;
use App\Services\ZammadTicketService;
use App\Support\ApiActor;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
class FeedbackController extends Controller
{
use RespondsWithJson;
public function __construct(
private readonly ZammadTicketService $zammadTickets,
) {
}
public function store(Request $request): JsonResponse
{
/** @var ApiActor $actor */
$actor = $request->attributes->get('api_actor');
$validated = $request->validate([
'type' => ['required', Rule::in(['bug', 'suggestion', 'other'])],
'title' => ['required', 'string', 'max:120'],
'message' => ['required', 'string', 'max:5000'],
'context' => ['sometimes', 'array'],
'context.page' => ['sometimes', 'string', 'max:500'],
'context.url' => ['sometimes', 'string', 'max:1000'],
'context.user_agent' => ['sometimes', 'string', 'max:500'],
'context.reporter' => ['sometimes', 'string', 'max:100'],
'context.reporter_name' => ['sometimes', 'string', 'max:200'],
'context.reported_at' => ['sometimes', 'string'],
]);
$ctx = $validated['context'] ?? [];
$feedback = Feedback::create([
'type' => $validated['type'],
'title' => $validated['title'],
'message' => $validated['message'],
'status' => 'open',
'reporter' => $ctx['reporter'] ?? ($actor?->identifier ?? null),
'reporter_name' => $ctx['reporter_name'] ?? null,
'page' => $ctx['page'] ?? null,
'url' => $ctx['url'] ?? null,
'user_agent' => $ctx['user_agent'] ?? null,
'reported_at' => isset($ctx['reported_at']) ? now()->parse($ctx['reported_at']) : now(),
]);
$this->zammadTickets->createTicketFromFeedback($feedback, $actor);
$feedback->refresh();
return $this->ok($this->serializeFeedback($feedback), [], 201);
}
public function index(Request $request): JsonResponse
{
/** @var ApiActor $actor */
$actor = $request->attributes->get('api_actor');
if (!$actor?->is_admin) {
return $this->fail('Forbidden', 'forbidden', 403);
}
$query = Feedback::query()->orderByDesc('created_at');
if ($request->filled('type')) {
$query->where('type', $request->query('type'));
}
if ($request->filled('status')) {
$query->where('status', $request->query('status'));
}
$items = $query->paginate(20);
return $this->ok($items);
}
public function update(Request $request, int $id): JsonResponse
{
/** @var ApiActor $actor */
$actor = $request->attributes->get('api_actor');
if (!$actor?->is_admin) {
return $this->fail('Forbidden', 'forbidden', 403);
}
$feedback = Feedback::findOrFail($id);
$validated = $request->validate([
'status' => ['sometimes', Rule::in(['open', 'in_progress', 'resolved', 'closed'])],
'admin_note' => ['sometimes', 'nullable', 'string', 'max:2000'],
]);
$feedback->update($validated);
return $this->ok($this->serializeFeedback($feedback));
}
/**
* @return array<string, mixed>
*/
private function serializeFeedback(Feedback $feedback): array
{
return [
'id' => $feedback->id,
'status' => $feedback->status,
'zammad_ticket_id' => $feedback->zammad_ticket_id,
'zammad_ticket_number' => $feedback->zammad_ticket_number,
'zammad_ticket_url' => $this->zammadTickets->ticketUrl($feedback),
'zammad_sync_error' => $feedback->zammad_sync_error,
];
}
}