Your IP : 216.73.217.79


Current Path : /var/www/v3.cesa.co.za/src/EventBundle/Controller/
Upload File :
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;
    }
}