Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
VerifyApieUser
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
4 / 4
13
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 handle
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
5
 supports
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
4
 loginAsUserOnSuccessfulResponse
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3namespace Apie\LaravelApie\Wrappers\Security;
4
5use Apie\Common\ApieFacade;
6use Apie\Common\ValueObjects\DecryptedAuthenticatedUser;
7use Apie\Core\Actions\ActionResponse;
8use Apie\Core\Actions\ActionResponseStatus;
9use Apie\Core\BoundedContext\BoundedContextId;
10use Apie\Core\ContextBuilders\ContextBuilderFactory;
11use Apie\Core\ContextConstants;
12use Apie\Core\Entities\EntityInterface;
13use Apie\RestApi\Exceptions\InvalidContentTypeException;
14use Closure;
15use Illuminate\Support\Facades\Auth;
16use Psr\Http\Message\ServerRequestInterface;
17use Symfony\Component\HttpFoundation\Request;
18use Symfony\Component\HttpFoundation\Response;
19
20class VerifyApieUser
21{
22    public function __construct(
23        private readonly ContextBuilderFactory $contextBuilderFactory,
24        private readonly ApieFacade $apieFacade,
25    ) {
26    }
27
28    public function handle(Request $request, Closure $next): Response
29    {
30        $psrRequest = app(ServerRequestInterface::class);
31        try {
32            $context = $this->contextBuilderFactory->createFromRequest($psrRequest);
33            $decryptedAuthenticatedUser = $context->getContext(DecryptedAuthenticatedUser::class, false);
34            if ($context->hasContext(ContextConstants::AUTHENTICATED_USER)
35                && $decryptedAuthenticatedUser instanceof DecryptedAuthenticatedUser) {
36                $userIdentifier = $decryptedAuthenticatedUser->toNative();
37                $user = resolve(ApieUserProvider::class)->retrieveById($userIdentifier);
38                Auth::login($user);
39            }
40        } catch (InvalidContentTypeException) {
41            // Ignore invalid content type exceptions here.
42        }
43        
44        if (!$this->supports($psrRequest)) {
45            return $next($request);
46        }
47        $context = $this->contextBuilderFactory->createFromRequest($psrRequest, [ContextConstants::CMS => true]);
48        $action = $this->apieFacade->createAction($context);
49        $actionResponse = $action($context, $context->getContext(ContextConstants::RAW_CONTENTS));
50        $this->loginAsUserOnSuccessfulResponse($psrRequest, $actionResponse);
51        return $next($request);
52    }
53
54    private function supports(ServerRequestInterface $request): bool
55    {
56        return $request->getAttribute('_is_apie', false)
57            && $request->getAttribute(ContextConstants::OPERATION_ID)
58            && str_starts_with($request->getAttribute(ContextConstants::OPERATION_ID), 'call-method-')
59            && 'verifyAuthentication' === $request->getAttribute(ContextConstants::METHOD_NAME);
60    }
61
62    private function loginAsUserOnSuccessfulResponse(ServerRequestInterface $psrRequest, ActionResponse $actionResponse): void
63    {
64        if ($actionResponse->status === ActionResponseStatus::SUCCESS && $actionResponse->result instanceof EntityInterface) {
65            $decryptedUserId = DecryptedAuthenticatedUser::createFromEntity(
66                $actionResponse->result,
67                new BoundedContextId($psrRequest->getAttribute(ContextConstants::BOUNDED_CONTEXT_ID)),
68                time() + 3600
69            );
70            $userIdentifier = $decryptedUserId->toNative();
71            $user = resolve(ApieUserProvider::class)->retrieveById($userIdentifier);
72            Auth::login($user);
73        }
74    }
75}