ApiIdentifier   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 64
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 27
c 2
b 0
f 1
dl 0
loc 64
rs 10
wmc 6

2 Methods

Rating   Name   Duplication   Size   Complexity  
A setError() 0 3 1
A identify() 0 32 5
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * BEdita, API-first content management framework
6
 * Copyright 2020 ChannelWeb Srl, Chialab Srl
7
 *
8
 * This file is part of BEdita: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published
10
 * by the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
14
 */
15
16
namespace BEdita\WebTools\Identifier;
17
18
use ArrayAccess;
19
use Authentication\Identifier\AbstractIdentifier;
20
use BEdita\SDK\BEditaClientException;
21
use BEdita\WebTools\ApiClientProvider;
22
use Cake\Log\LogTrait;
23
use Cake\Utility\Hash;
24
use Psr\Log\LogLevel;
25
26
/**
27
 * Identifier for authentication using BEdita API /auth endpoint.
28
 */
29
class ApiIdentifier extends AbstractIdentifier
30
{
31
    use LogTrait;
32
33
    /**
34
     * Default configuration.
35
     *
36
     * - fields: the fields used for identify user
37
     *
38
     * @var array
39
     */
40
    protected array $_defaultConfig = [
41
        'fields' => [
42
            self::CREDENTIAL_USERNAME => 'username',
43
            self::CREDENTIAL_PASSWORD => 'password',
44
        ],
45
    ];
46
47
    /**
48
     * @inheritDoc
49
     */
50
    public function identify(array $data): ArrayAccess|array|null
51
    {
52
        $usernameField = $this->getConfig('fields.' . self::CREDENTIAL_USERNAME);
53
        $passwordField = $this->getConfig('fields.' . self::CREDENTIAL_PASSWORD);
54
        if (!isset($data[$usernameField]) || !isset($data[$passwordField])) {
55
            return null;
56
        }
57
58
        /** @var \BEdita\SDK\BEditaClient $apiClient */
59
        $apiClient = ApiClientProvider::getApiClient();
60
        try {
61
            $result = $apiClient->authenticate(
62
                $data[$usernameField],
63
                $data[$passwordField]
64
            );
65
            if (empty($result['meta'])) {
66
                $this->setError('Invalid username or password');
67
68
                return null;
69
            }
70
            $tokens = $result['meta'];
71
            $result = $apiClient->get('/auth/user', null, ['Authorization' => sprintf('Bearer %s', $tokens['jwt'])]);
72
        } catch (BEditaClientException $e) {
73
            $this->log('Login failed - ' . $e->getMessage(), LogLevel::INFO);
74
            $this->setError($e->getMessage());
75
76
            return null;
77
        }
78
79
        $roles = Hash::extract($result, 'included.{n}.attributes.name');
80
81
        return $result['data'] + compact('tokens') + compact('roles');
82
    }
83
84
    /**
85
     * Add error message to `self::_errors`
86
     *
87
     * @param string $message The error message
88
     * @return void
89
     */
90
    protected function setError(string $message): void
91
    {
92
        $this->_errors[] = $message;
93
    }
94
}
95