• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FastyBird / accounts-module / 12030623467

26 Nov 2024 12:29PM UTC coverage: 70.389%. Remained the same
12030623467

push

github

actions-user
Added missing package repository (#331)

2370 of 3367 relevant lines covered (70.39%)

40.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.37
/src/Controllers/AccountIdentitiesV1.php
1
<?php declare(strict_types = 1);
2

3
/**
4
 * AccountIdentitiesV1.php
5
 *
6
 * @license        More in LICENSE.md
7
 * @copyright      http://www.fastybird.com
8
 * @author         Adam Kadlec <adam.kadlec@fastybird.com>
9
 * @package        FastyBird:AccountsModule!
10
 * @subpackage     Controllers
11
 * @since          1.0.0
12
 *
13
 * @date           31.03.20
14
 */
15

16
namespace FastyBird\Module\Accounts\Controllers;
17

18
use Doctrine;
19
use Exception;
20
use FastyBird\Core\Application\Exceptions as ApplicationExceptions;
21
use FastyBird\Core\Tools\Exceptions as ToolsExceptions;
22
use FastyBird\Core\Tools\Helpers as ToolsHelpers;
23
use FastyBird\JsonApi\Exceptions as JsonApiExceptions;
24
use FastyBird\Library\Metadata\Types as MetadataTypes;
25
use FastyBird\Module\Accounts\Controllers;
26
use FastyBird\Module\Accounts\Entities;
27
use FastyBird\Module\Accounts\Exceptions;
28
use FastyBird\Module\Accounts\Models;
29
use FastyBird\Module\Accounts\Queries;
30
use FastyBird\Module\Accounts\Router;
31
use FastyBird\Module\Accounts\Schemas;
32
use Fig\Http\Message\StatusCodeInterface;
33
use InvalidArgumentException;
34
use IPub\DoctrineOrmQuery\Exceptions as DoctrineOrmQueryExceptions;
35
use IPub\JsonAPIDocument\Objects as JsonAPIDocumentObjects;
36
use Nette\Utils;
37
use Psr\Http\Message;
38
use RuntimeException;
39
use Throwable;
40
use function is_scalar;
41
use function strtolower;
42
use function strval;
43

44
/**
45
 * Account identity controller
46
 *
47
 * @package        FastyBird:AccountsModule!
48
 * @subpackage     Controllers
49
 *
50
 * @author         Adam Kadlec <adam.kadlec@fastybird.com>
51
 *
52
 * @Secured\User(loggedIn)
53
 */
54
final class AccountIdentitiesV1 extends BaseV1
55
{
56

57
        use Controllers\Finders\TIdentity;
58

59
        public function __construct(
60
                protected readonly Models\Entities\Identities\IdentitiesRepository $identitiesRepository,
61
                private readonly Models\Entities\Identities\IdentitiesManager $identitiesManager,
62
        )
63
        {
64
        }
300✔
65

66
        /**
67
         * @throws ApplicationExceptions\InvalidState
68
         * @throws Exceptions\InvalidState
69
         * @throws JsonApiExceptions\JsonApi
70
         * @throws ToolsExceptions\InvalidState
71
         */
72
        public function index(
73
                Message\ServerRequestInterface $request,
74
                Message\ResponseInterface $response,
75
        ): Message\ResponseInterface
76
        {
77
                $findQuery = new Queries\Entities\FindIdentities();
2✔
78
                $findQuery->forAccount($this->findAccount());
2✔
79

80
                $identities = $this->identitiesRepository->getResultSet($findQuery);
2✔
81

82
                // @phpstan-ignore-next-line
83
                return $this->buildResponse($request, $response, $identities);
2✔
84
        }
85

86
        /**
87
         * @throws DoctrineOrmQueryExceptions\InvalidStateException
88
         * @throws DoctrineOrmQueryExceptions\QueryException
89
         * @throws Exception
90
         * @throws JsonApiExceptions\JsonApi
91
         */
92
        public function read(
93
                Message\ServerRequestInterface $request,
94
                Message\ResponseInterface $response,
95
        ): Message\ResponseInterface
96
        {
97
                // Find identity
98
                $identity = $this->findIdentity($request, $this->findAccount());
3✔
99

100
                return $this->buildResponse($request, $response, $identity);
1✔
101
        }
102

103
        /**
104
         * @throws Doctrine\DBAL\ConnectionException
105
         * @throws Doctrine\DBAL\Exception
106
         * @throws DoctrineOrmQueryExceptions\InvalidStateException
107
         * @throws DoctrineOrmQueryExceptions\QueryException
108
         * @throws Exceptions\Runtime
109
         * @throws InvalidArgumentException
110
         * @throws JsonApiExceptions\JsonApi
111
         * @throws RuntimeException
112
         */
113
        public function update(
114
                Message\ServerRequestInterface $request,
115
                Message\ResponseInterface $response,
116
        ): Message\ResponseInterface
117
        {
118
                $document = $this->createDocument($request);
7✔
119

120
                $identity = $this->findIdentity($request, $this->findAccount());
7✔
121

122
                $this->validateIdentifier($request, $document);
5✔
123

124
                try {
125
                        // Start transaction connection to the database
126
                        $this->getOrmConnection()->beginTransaction();
4✔
127

128
                        if ($document->getResource()->getType() === Schemas\Identities\Identity::SCHEMA_TYPE) {
4✔
129
                                $attributes = $document->getResource()->getAttributes();
3✔
130

131
                                $passwordAttribute = $attributes->get('password');
3✔
132

133
                                if (
134
                                        !$passwordAttribute instanceof JsonAPIDocumentObjects\IStandardObject
3✔
135
                                        || !$passwordAttribute->has('current')
3✔
136
                                        || !is_scalar($passwordAttribute->get('current'))
3✔
137
                                ) {
138
                                        throw new JsonApiExceptions\JsonApiError(
1✔
139
                                                StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY,
1✔
140
                                                strval(
1✔
141
                                                        $this->translator->translate('//accounts-module.base.messages.missingAttribute.heading'),
1✔
142
                                                ),
1✔
143
                                                strval(
1✔
144
                                                        $this->translator->translate('//accounts-module.base.messages.missingAttribute.message'),
1✔
145
                                                ),
1✔
146
                                                [
1✔
147
                                                        'pointer' => '/data/attributes/password/current',
1✔
148
                                                ],
1✔
149
                                        );
1✔
150
                                }
151

152
                                if (!$passwordAttribute->has('new') || !is_scalar($passwordAttribute->get('new'))) {
2✔
153
                                        throw new JsonApiExceptions\JsonApiError(
×
154
                                                StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY,
×
155
                                                strval(
×
156
                                                        $this->translator->translate('//accounts-module.base.messages.missingAttribute.heading'),
×
157
                                                ),
×
158
                                                strval(
×
159
                                                        $this->translator->translate('//accounts-module.base.messages.missingAttribute.message'),
×
160
                                                ),
×
161
                                                [
×
162
                                                        'pointer' => '/data/attributes/password/new',
×
163
                                                ],
×
164
                                        );
×
165
                                }
166

167
                                if (!$identity->verifyPassword((string) $passwordAttribute->get('current'))) {
2✔
168
                                        throw new JsonApiExceptions\JsonApiError(
1✔
169
                                                StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY,
1✔
170
                                                strval(
1✔
171
                                                        $this->translator->translate('//accounts-module.base.messages.invalidAttribute.heading'),
1✔
172
                                                ),
1✔
173
                                                strval(
1✔
174
                                                        $this->translator->translate('//accounts-module.base.messages.invalidAttribute.message'),
1✔
175
                                                ),
1✔
176
                                                [
1✔
177
                                                        'pointer' => '/data/attributes/password/current',
1✔
178
                                                ],
1✔
179
                                        );
1✔
180
                                }
181

182
                                $update = new Utils\ArrayHash();
1✔
183
                                $update->offsetSet('password', (string) $passwordAttribute->get('new'));
1✔
184

185
                                // Update item in database
186
                                $this->identitiesManager->update($identity, $update);
1✔
187

188
                        } else {
189
                                throw new JsonApiExceptions\JsonApiError(
1✔
190
                                        StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY,
1✔
191
                                        strval($this->translator->translate('//accounts-module.base.messages.invalidType.heading')),
1✔
192
                                        strval($this->translator->translate('//accounts-module.base.messages.invalidType.message')),
1✔
193
                                        [
1✔
194
                                                'pointer' => '/data/type',
1✔
195
                                        ],
1✔
196
                                );
1✔
197
                        }
198

199
                        // Commit all changes into database
200
                        $this->getOrmConnection()->commit();
1✔
201

202
                } catch (JsonApiExceptions\JsonApi $ex) {
3✔
203
                        throw $ex;
3✔
204
                } catch (Throwable $ex) {
×
205
                        // Log caught exception
206
                        $this->logger->error(
×
207
                                'An unhandled error occurred',
×
208
                                [
×
209
                                        'source' => MetadataTypes\Sources\Module::ACCOUNTS->value,
×
210
                                        'type' => 'account-identities-controller',
×
211
                                        'exception' => ToolsHelpers\Logger::buildException($ex),
×
212
                                ],
×
213
                        );
×
214

215
                        throw new JsonApiExceptions\JsonApiError(
×
216
                                StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY,
×
217
                                strval($this->translator->translate('//accounts-module.base.messages.notUpdated.heading')),
×
218
                                strval($this->translator->translate('//accounts-module.base.messages.notUpdated.message')),
×
219
                        );
×
220
                } finally {
221
                        // Revert all changes when error occur
222
                        if ($this->getOrmConnection()->isTransactionActive()) {
4✔
223
                                $this->getOrmConnection()->rollBack();
3✔
224
                        }
225
                }
226

227
                return $response->withStatus(StatusCodeInterface::STATUS_NO_CONTENT);
1✔
228
        }
229

230
        /**
231
         * @throws DoctrineOrmQueryExceptions\QueryException
232
         * @throws DoctrineOrmQueryExceptions\InvalidStateException
233
         * @throws Exception
234
         * @throws JsonApiExceptions\JsonApi
235
         */
236
        public function readRelationship(
237
                Message\ServerRequestInterface $request,
238
                Message\ResponseInterface $response,
239
        ): Message\ResponseInterface
240
        {
241
                $identity = $this->findIdentity($request, $this->findAccount());
4✔
242

243
                // & relation entity name
244
                $relationEntity = strtolower(strval($request->getAttribute(Router\ApiRoutes::RELATION_ENTITY)));
2✔
245

246
                if ($relationEntity === Schemas\Identities\Identity::RELATIONSHIPS_ACCOUNT) {
2✔
247
                        return $this->buildResponse($request, $response, $identity->getAccount());
1✔
248
                }
249

250
                return parent::readRelationship($request, $response);
1✔
251
        }
252

253
        /**
254
         * @throws JsonApiExceptions\JsonApiError
255
         */
256
        private function findAccount(): Entities\Accounts\Account
257
        {
258
                if ($this->user->getAccount() === null) {
16✔
259
                        throw new JsonApiExceptions\JsonApiError(
×
260
                                StatusCodeInterface::STATUS_FORBIDDEN,
×
261
                                strval($this->translator->translate('//accounts-module.base.messages.forbidden.heading')),
×
262
                                strval($this->translator->translate('//accounts-module.base.messages.forbidden.message')),
×
263
                        );
×
264
                }
265

266
                return $this->user->getAccount();
16✔
267
        }
268

269
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc