Passed
Push — master ( 5d2f4a...4ba7a2 )
by Petr
07:39
created

AccountsDatabase   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 182
Duplicated Lines 0 %

Test Coverage

Coverage 5.56%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 91
c 1
b 0
f 0
dl 0
loc 182
ccs 5
cts 90
cp 0.0556
rs 10
wmc 30

12 Methods

Rating   Name   Duplication   Size   Complexity  
A getByLogin() 0 9 2
A updatePassword() 0 11 2
A updateAccount() 0 14 2
A readAccounts() 0 8 2
A checkLogin() 0 14 5
A updateCertKeys() 0 12 2
A authenticate() 0 18 6
A createAccount() 0 12 2
A getCertData() 0 7 2
A __construct() 0 5 1
A deleteAccount() 0 9 2
A getDataOnly() 0 7 2
1
<?php
2
3
namespace kalanis\kw_auth_sources\Sources\Mapper;
4
5
6
use kalanis\kw_accounts\AccountsException;
7
use kalanis\kw_accounts\Interfaces as acc_interfaces;
8
use kalanis\kw_auth_sources\AuthSourcesException;
9
use kalanis\kw_auth_sources\Interfaces;
10
use kalanis\kw_auth_sources\Traits\TLang;
11
use kalanis\kw_auth_sources\Traits\TSeparated;
12
use kalanis\kw_mapper\MapperException;
13
use kalanis\kw_mapper\Search\Search;
14
15
16
/**
17
 * Class Database
18
 * @package kalanis\kw_auth_sources\Sources\Mapper
19
 * Authenticate via Database
20
 * need kw_mapper!
21
 * @codeCoverageIgnore because access external content
22
 */
23
class AccountsDatabase implements acc_interfaces\IAuthCert, acc_interfaces\IProcessAccounts
24
{
25
    use TLang;
26
    use TSeparated;
27
28
    /** @var Interfaces\IHashes */
29
    protected $passMode = null;
30
    /** @var Database\UsersRecord */
31
    protected $usersRecord = null;
32
33 1
    public function __construct(Interfaces\IHashes $mode, ?Interfaces\IKAusTranslations $lang = null)
34
    {
35 1
        $this->setAusLang($lang);
36 1
        $this->passMode = $mode;
37 1
        $this->usersRecord = new Database\UsersRecord();
38 1
    }
39
40
    public function authenticate(string $userName, array $params = []): ?acc_interfaces\IUser
41
    {
42
        if (!isset($params['password'])) {
43
            throw new AccountsException($this->getAusLang()->kauPassMustBeSet());
44
        }
45
        try {
46
            $record = $this->getByLogin($userName);
47
            if (empty($record)) {
48
                return null;
49
            }
50
51
            if (!$this->passMode->checkHash(isset($params['password']) ? strval($params['password']): '', $record->pass)) {
52
                return null;
53
            }
54
            return $record;
55
56
        } catch (AuthSourcesException | MapperException $ex) {
57
            throw new AccountsException($ex->getMessage(), $ex->getCode(), $ex);
58
        }
59
    }
60
61
    public function getDataOnly(string $userName): ?acc_interfaces\IUser
62
    {
63
        try {
64
            return $this->getByLogin($userName);
65
66
        } catch (MapperException $ex) {
67
            throw new AccountsException($ex->getMessage(), $ex->getCode(), $ex);
68
        }
69
    }
70
71
    public function updateCertKeys(string $userName, ?string $certKey, ?string $certSalt): bool
72
    {
73
        try {
74
            $record = clone $this->usersRecord;
75
            $record->login = $userName;
76
            $record->load();
77
            $record->cert = strval($certKey);
78
            $record->salt = strval($certSalt);
79
            return $record->save();
80
81
        } catch (MapperException $ex) {
82
            throw new AccountsException($ex->getMessage(), $ex->getCode(), $ex);
83
        }
84
    }
85
86
    public function getCertData(string $userName): ?acc_interfaces\IUserCert
87
    {
88
        try {
89
            return $this->getByLogin($userName);
90
91
        } catch (MapperException $ex) {
92
            throw new AccountsException($ex->getMessage(), $ex->getCode(), $ex);
93
        }
94
    }
95
96
    /**
97
     * @param string $login
98
     * @throws MapperException
99
     * @return Database\UsersRecord|null
100
     */
101
    protected function getByLogin(string $login): ?Database\UsersRecord
102
    {
103
        $record = clone $this->usersRecord;
104
        $record->login = $login;
105
        if (empty($record->count())) {
106
            return null;
107
        }
108
        $record->load();
109
        return $record;
110
    }
111
112
    public function createAccount(acc_interfaces\IUser $user, string $password): bool
113
    {
114
        try {
115
            $record = clone $this->usersRecord;
116
            $this->checkLogin($user->getAuthName());
117
            $record->login = $user->getAuthName();
118
            $record->groupId = $user->getGroup();
119
            $record->display = $user->getDisplayName();
120
            return $record->save(true);
121
122
        } catch (MapperException $ex) {
123
            throw new AccountsException($ex->getMessage(), $ex->getCode(), $ex);
124
        }
125
    }
126
127
    /**
128
     * @throws AccountsException
129
     * @return Database\UsersRecord[]
130
     */
131
    public function readAccounts(): array
132
    {
133
        try {
134
            $search = new Search(clone $this->usersRecord);
135
            return $search->getResults();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $search->getResults() returns the type kalanis\kw_mapper\Records\ARecord[] which is incompatible with the return type mandated by kalanis\kw_accounts\Inte...ccounts::readAccounts() of kalanis\kw_accounts\Interfaces\IUser[].

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
136
137
        } catch (MapperException $ex) {
138
            throw new AccountsException($ex->getMessage(), $ex->getCode(), $ex);
139
        }
140
    }
141
142
    public function updateAccount(acc_interfaces\IUser $user): bool
143
    {
144
        try {
145
            $this->checkLogin($user->getAuthName(), $user->getAuthId());
146
            $record = clone $this->usersRecord;
147
            $record->id = $user->getAuthId();
148
            $record->load();
149
            $record->login = $user->getAuthName();
150
            $record->groupId = $user->getGroup();
151
            $record->display = $user->getDisplayName();
152
            return $record->save();
153
154
        } catch (MapperException $ex) {
155
            throw new AccountsException($ex->getMessage(), $ex->getCode(), $ex);
156
        }
157
    }
158
159
    public function updatePassword(string $userName, string $passWord): bool
160
    {
161
        try {
162
            $record = clone $this->usersRecord;
163
            $record->login = $userName;
164
            $record->load();
165
            $record->pass = $this->passMode->createHash($passWord);
166
            return $record->save();
167
168
        } catch (AuthSourcesException | MapperException $ex) {
169
            throw new AccountsException($ex->getMessage(), $ex->getCode(), $ex);
170
        }
171
    }
172
173
    public function deleteAccount(string $userName): bool
174
    {
175
        try {
176
            $record = clone $this->usersRecord;
177
            $record->login = $userName;
178
            return $record->delete();
179
180
        } catch (MapperException $ex) {
181
            throw new AccountsException($ex->getMessage(), $ex->getCode(), $ex);
182
        }
183
    }
184
185
    /**
186
     * @param string $login
187
     * @param string $id
188
     * @throws AccountsException
189
     * @throws MapperException
190
     */
191
    protected function checkLogin(string $login, string $id = '0'): void
192
    {
193
        $user = clone $this->usersRecord;
194
        $user->login = $login;
195
        $amount = $user->count();
196
        if (1 > $amount) {
197
            return;
198
        }
199
        if (1 < $amount) {
200
            throw new AccountsException('Too many users with that login!');
201
        }
202
        $user->load();
203
        if ($id && ($user->id != $id)) {
204
            throw new AccountsException('Login already used.');
205
        }
206
    }
207
}
208