Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
ConsoleLoginContextBuilder
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
2 / 2
11
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
 process
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
10
1<?php
2namespace Apie\Console\ContextBuilders;
3
4use Apie\Common\Interfaces\CheckLoginStatusInterface;
5use Apie\Common\ValueObjects\DecryptedAuthenticatedUser;
6use Apie\Common\Wrappers\TextEncrypter;
7use Apie\Console\ConsoleCliStorage;
8use Apie\Core\Context\ApieContext;
9use Apie\Core\ContextBuilders\ContextBuilderInterface;
10use Apie\Core\ContextConstants;
11use Apie\Core\Datalayers\ApieDatalayer;
12use Apie\Core\Exceptions\EntityNotFoundException;
13use Apie\Core\ValueObjects\Exceptions\InvalidStringForValueObjectException;
14use Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException;
15use Psr\Http\Message\ServerRequestInterface;
16
17class ConsoleLoginContextBuilder implements ContextBuilderInterface
18{
19    public function __construct(
20        private readonly ConsoleCliStorage $consoleCliStorage,
21    ) {
22    }
23
24    public function process(ApieContext $context): ApieContext
25    {
26        $textEncrypter = $context->getContext(TextEncrypter::class, false);
27        $apieDatalayer = $context->getContext(ApieDatalayer::class, false);
28        $request = $context->getContext(ServerRequestInterface::class, false);
29        if ($request || !$textEncrypter || !$apieDatalayer) {
30            // Storage only available in apie/console
31            return $context;
32        }
33        $cliStorage = $this->consoleCliStorage;
34        $authenticated = $cliStorage->restore('_APIE_AUTHENTICATED');
35        if ($authenticated === null) {
36            return $context;
37        }
38        try {
39            $decrypted = DecryptedAuthenticatedUser::fromNative($textEncrypter->decrypt($authenticated));
40            if ($decrypted->isExpired()) {
41                $cliStorage->remove('_APIE_AUTHENTICATED');
42                return $context;
43            }
44            $entity = $apieDatalayer->find($decrypted->getId(), $decrypted->getBoundedContextId());
45            if ($entity instanceof CheckLoginStatusInterface && $entity->isDisabled()) {
46                $cliStorage->remove('_APIE_AUTHENTICATED');
47                return $context;
48            }
49            return $context->withContext(ContextConstants::AUTHENTICATED_USER, $entity)
50                ->withContext(DecryptedAuthenticatedUser::class, $decrypted);
51        } catch (WrongKeyOrModifiedCiphertextException) {
52            // key is not removed, because it might be a valid key in another project
53            return $context;
54        } catch (InvalidStringForValueObjectException|EntityNotFoundException) {
55            $cliStorage->remove('_APIE_AUTHENTICATED');
56            return $context;
57        }
58    }
59}