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

FastyBird / simple-auth / 10030599651

21 Jul 2024 06:48PM UTC coverage: 68.983% (+1.1%) from 67.871%
10030599651

push

github

web-flow
User roles check as was before casbin (#11)

* User roles check as was before casbin

* Fix interface

* Use storage instead of user

* QA fixes

45 of 49 new or added lines in 4 files covered. (91.84%)

1 existing line in 1 file now uncovered.

536 of 777 relevant lines covered (68.98%)

5.97 hits per line

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

52.0
/src/Subscribers/User.php
1
<?php declare(strict_types = 1);
2

3
/**
4
 * User.php
5
 *
6
 * @license        More in LICENSE.md
7
 * @copyright      https://www.fastybird.com
8
 * @author         Adam Kadlec <adam.kadlec@fastybird.com>
9
 * @package        FastyBird:SimpleAuth!
10
 * @subpackage     Subscribers
11
 * @since          0.1.0
12
 *
13
 * @date           14.07.20
14
 */
15

16
namespace FastyBird\SimpleAuth\Subscribers;
17

18
use Doctrine\Common;
19
use Doctrine\ORM;
20
use Doctrine\Persistence;
21
use FastyBird\SimpleAuth\Exceptions;
22
use FastyBird\SimpleAuth\Mapping;
23
use FastyBird\SimpleAuth\Security;
24
use Nette;
25
use ReflectionException;
26
use function array_key_exists;
27
use function is_array;
28

29
/**
30
 * Doctrine entities events
31
 *
32
 * @template T of object
33
 *
34
 * @package        FastyBird:SimpleAuth!
35
 * @subpackage     Subscribers
36
 * @author         Adam Kadlec <adam.kadlec@fastybird.com>
37
 */
38
final class User implements Common\EventSubscriber
39
{
40

41
        use Nette\SmartObject;
42

43
        /**
44
         * @param Mapping\Driver\Owner<T> $driver
45
         */
46
        public function __construct(
47
                private readonly Mapping\Driver\Owner $driver,
48
                private readonly Security\IUserStorage $userStorage,
49
        )
50
        {
51
        }
12✔
52

53
        /**
54
         * Register events
55
         *
56
         * @return array<string>
57
         */
58
        public function getSubscribedEvents(): array
59
        {
60
                return [
13✔
61
                        ORM\Events::loadClassMetadata,
13✔
62
                        ORM\Events::onFlush,
13✔
63
                ];
13✔
64
        }
65

66
        /**
67
         * @throws Exceptions\InvalidMapping
68
         * @throws ORM\Mapping\MappingException
69
         */
70
        public function loadClassMetadata(
71
                ORM\Event\LoadClassMetadataEventArgs $eventArgs,
72
        ): void
73
        {
74
                /** @var ORM\Mapping\ClassMetadata<T> $classMetadata */
75
                $classMetadata = $eventArgs->getClassMetadata();
3✔
76

77
                $this->driver->loadMetadataForObjectClass($eventArgs->getObjectManager(), $classMetadata);
3✔
78

79
                // Register pre persist event
80
                $this->registerEvent($classMetadata, ORM\Events::prePersist);
3✔
81
        }
82

83
        /**
84
         * @param ORM\Mapping\ClassMetadata<T> $classMetadata
85
         *
86
         * @throws ORM\Mapping\MappingException
87
         */
88
        private function registerEvent(
89
                ORM\Mapping\ClassMetadata $classMetadata,
90
                string $eventName,
91
        ): void
92
        {
93
                if (!$this->hasRegisteredListener($classMetadata, $eventName, self::class)) {
3✔
94
                        $classMetadata->addEntityListener($eventName, self::class, $eventName);
3✔
95
                }
96
        }
97

98
        /**
99
         * @param ORM\Mapping\ClassMetadata<T> $classMetadata
100
         */
101
        private function hasRegisteredListener(
102
                ORM\Mapping\ClassMetadata $classMetadata,
103
                string $eventName,
104
                string $listenerClass,
105
        ): bool
106
        {
107
                if (!isset($classMetadata->entityListeners[$eventName])) {
3✔
108
                        return false;
3✔
109
                }
110

111
                foreach ($classMetadata->entityListeners[$eventName] as $listener) {
3✔
112
                        if ($listener['class'] === $listenerClass && $listener['method'] === $eventName) {
3✔
113
                                return true;
3✔
114
                        }
115
                }
116

117
                return false;
×
118
        }
119

120
        /**
121
         * @throws Exceptions\InvalidMapping
122
         * @throws ORM\Mapping\MappingException
123
         * @throws ORM\ORMInvalidArgumentException
124
         * @throws Persistence\Mapping\MappingException
125
         * @throws ReflectionException
126
         */
127
        public function onFlush(ORM\Event\OnFlushEventArgs $eventArgs): void
128
        {
129
                $manager = $eventArgs->getObjectManager();
12✔
130
                $uow = $manager->getUnitOfWork();
12✔
131

132
                // Check all scheduled updates
133
                foreach ($uow->getScheduledEntityUpdates() as $object) {
12✔
134
                        /** @var ORM\Mapping\ClassMetadata<T> $classMetadata */
135
                        $classMetadata = $manager->getClassMetadata($object::class);
6✔
136

137
                        $config = $this->driver->getObjectConfigurations($manager, $classMetadata->getName());
6✔
138

139
                        if ($config !== []) {
6✔
140
                                $changeSet = $uow->getEntityChangeSet($object);
×
141
                                $needChanges = false;
×
142

143
                                if ($uow->isScheduledForInsert($object) && isset($config['create'])) {
×
144
                                        // @phpstan-ignore-next-line
145
                                        foreach ($config['create'] as $field) {
×
146
                                                // Field can not exist in change set, when persisting embedded document without parent for example
147
                                                // @phpstan-ignore-next-line
148
                                                $new = array_key_exists($field, $changeSet) ? $changeSet[$field][1] : false;
×
149

150
                                                if ($new === null) { // let manual values
×
151
                                                        $needChanges = true;
×
152
                                                        // @phpstan-ignore-next-line
153
                                                        $this->updateField($uow, $object, $classMetadata, $field);
×
154
                                                }
155
                                        }
156
                                }
157

158
                                if ($needChanges) {
×
159
                                        $uow->recomputeSingleEntityChangeSet($classMetadata, $object);
×
160
                                }
161
                        }
162
                }
163
        }
164

165
        /**
166
         * Updates a field
167
         *
168
         * @param ORM\Mapping\ClassMetadata<T> $classMetadata
169
         */
170
        private function updateField(
171
                ORM\UnitOfWork $uow,
172
                mixed $object,
173
                ORM\Mapping\ClassMetadata $classMetadata,
174
                string $field,
175
        ): void
176
        {
177
                $property = $classMetadata->getReflectionProperty($field);
×
178

179
                // @phpstan-ignore-next-line
180
                $oldValue = $property->getValue($object);
×
NEW
181
                $newValue = $this->userStorage->getIdentity()?->getId()->toString();
×
182

183
                // @phpstan-ignore-next-line
184
                $property->setValue($object, $newValue);
×
185

186
                // @phpstan-ignore-next-line
187
                $uow->propertyChanged($object, $field, $oldValue, $newValue);
×
188
                // @phpstan-ignore-next-line
189
                $uow->scheduleExtraUpdate($object, [
×
190
                        $field => [$oldValue, $newValue],
×
191
                ]);
×
192
        }
193

194
        /**
195
         * @throws Exceptions\InvalidMapping
196
         * @throws ORM\Mapping\MappingException
197
         * @throws Persistence\Mapping\MappingException
198
         * @throws ReflectionException
199
         */
200
        public function prePersist(
201
                mixed $entity,
202
                ORM\Event\PrePersistEventArgs $eventArgs,
203
        ): void
204
        {
205
                $manager = $eventArgs->getObjectManager();
12✔
206
                $uow = $manager->getUnitOfWork();
12✔
207
                /** @var ORM\Mapping\ClassMetadata<T> $classMetadata */
208
                $classMetadata = $manager->getClassMetadata($entity::class); // @phpstan-ignore-line
12✔
209

210
                $config = $this->driver->getObjectConfigurations($manager, $classMetadata->getName());
12✔
211

212
                if ($config !== []) {
12✔
213
                        if (isset($config['create']) && is_array($config['create'])) {
×
214
                                $this->updateFields($config['create'], $uow, $entity, $classMetadata);
×
215
                        }
216
                }
217
        }
218

219
        /**
220
         * @param array<string> $fields
221
         * @param ORM\Mapping\ClassMetadata<T> $classMetadata
222
         */
223
        private function updateFields(
224
                array $fields,
225
                ORM\UnitOfWork $uow,
226
                mixed $object,
227
                ORM\Mapping\ClassMetadata $classMetadata,
228
        ): void
229
        {
230
                foreach ($fields as $field) {
×
231
                        // @phpstan-ignore-next-line
232
                        if ($classMetadata->getReflectionProperty($field)->getValue($object) === null) { // let manual values
×
233
                                $this->updateField($uow, $object, $classMetadata, $field);
×
234
                        }
235
                }
236
        }
237

238
}
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