| Current Path : /var/www/v3.cesa.co.za/src/EventBundle/Controller/ |
| Current File : /var/www/v3.cesa.co.za/src/EventBundle/Controller/SchoolWeeksCoursesDashboardExternalController.php |
<?php
namespace App\EventBundle\Controller;
use App\EventBundle\Services\SchoolWeeksCoursesDashboardService;
use App\MemberBundle\Http\CesaMainExternalCaller;
use App\UserBundle\Service\Echasl23SsoTicketService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* Trusted embed for SCE Weeks/Courses dashboard (echasl23 server-side proxy + SSO ticket).
*/
final class SchoolWeeksCoursesDashboardExternalController extends AbstractController
{
#[Route('/api/external/echasl23/weeks-courses/embed', name: 'echasl23_external_weeks_courses_embed', methods: ['POST', 'GET'])]
public function embed(
Request $request,
Echasl23SsoTicketService $ssoTicketService,
SchoolWeeksCoursesDashboardService $dashboardService,
): Response {
$deny = $this->denyIfNotTrusted($request);
if ($deny instanceof Response) {
return $deny;
}
$ticket = trim((string) (
$request->request->get('ticket')
?? $request->query->get('ticket')
?? ''
));
if ($ticket === '' && $request->getContent() !== '') {
$payload = json_decode((string) $request->getContent(), true);
if (is_array($payload) && isset($payload['ticket'])) {
$ticket = trim((string) $payload['ticket']);
}
}
if ($ticket === '') {
return new Response('Missing SSO ticket.', Response::HTTP_UNAUTHORIZED, ['Content-Type' => 'text/plain; charset=UTF-8']);
}
$auth = $ssoTicketService->authenticateFromTicketDetailed($ticket);
$user = $auth['user'];
if ($user === null) {
$message = $auth['error'] !== '' ? $auth['error'] : 'Invalid or expired SSO ticket.';
return new Response($message, Response::HTTP_UNAUTHORIZED, ['Content-Type' => 'text/plain; charset=UTF-8']);
}
$filters = [
'from' => $this->readFilter($request, 'from'),
'to' => $this->readFilter($request, 'to'),
'q' => $this->readFilter($request, 'q'),
'page' => $this->readFilter($request, 'page'),
'per_page' => $this->readFilter($request, 'per_page'),
'sort' => $this->readFilter($request, 'sort'),
'dir' => $this->readFilter($request, 'dir'),
];
$export = $this->readFilter($request, 'export');
if ($export === '1' || strcasecmp((string) $export, 'xlsx') === 0) {
$binary = $dashboardService->buildExcelBinary($filters);
$filename = 'sce-weeks-courses-' . date('Ymd-His') . '.xlsx';
return new Response($binary, Response::HTTP_OK, [
'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'Content-Disposition' => 'attachment; filename="' . $filename . '"',
'Cache-Control' => 'no-store, no-cache, must-revalidate',
]);
}
$pageData = $dashboardService->getDashboardPage($filters);
$html = $this->renderView('@EventBundle/Dashboard/weeks_courses_dashboard_embed.html.twig', [
'rows' => $pageData['rows'],
'filters' => $pageData['filters'],
'total' => $pageData['total'],
'page' => $pageData['page'],
'per_page' => $pageData['per_page'],
'pages' => $pageData['pages'],
'per_page_options' => SchoolWeeksCoursesDashboardService::PER_PAGE_OPTIONS,
'username' => $user->getUsername(),
]);
return new Response($html, Response::HTTP_OK, ['Content-Type' => 'text/html; charset=UTF-8']);
}
private function readFilter(Request $request, string $key): ?string
{
$value = $request->request->get($key) ?? $request->query->get($key);
if ($value === null) {
$payload = json_decode((string) $request->getContent(), true);
if (is_array($payload) && array_key_exists($key, $payload)) {
$value = $payload[$key];
}
}
$value = is_scalar($value) ? trim((string) $value) : '';
return $value !== '' ? $value : null;
}
private function denyIfNotTrusted(Request $request): ?Response
{
$csv = CesaMainExternalCaller::getAllowedIpsCsv($request);
if (trim($csv) === '') {
return new Response(
'API IP whitelist is not configured (CESA_MAIN_ALLOWED_IPS).',
Response::HTTP_FORBIDDEN,
['Content-Type' => 'text/plain; charset=UTF-8']
);
}
if (!CesaMainExternalCaller::isAuthorised($request, $csv)) {
return new Response('Forbidden.', Response::HTTP_FORBIDDEN, ['Content-Type' => 'text/plain; charset=UTF-8']);
}
return null;
}
}