Completed
Push — master ( 659d82...f5ba6f )
by Arthur
05:40
created

KeyFobAccess::verifyForDevice()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 37
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 37
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 18
nc 7
nop 3
1
<?php namespace BB\Services;
2
3
use BB\Entities\Equipment;
4
use BB\Entities\KeyFob;
5
use BB\Entities\User;
6
use BB\Events\MemberActivity;
7
use BB\Exceptions\ValidationException;
8
use BB\Repo\ActivityRepository;
9
use BB\Repo\EquipmentRepository;
10
use BB\Repo\InductionRepository;
11
use Carbon\Carbon;
12
use Illuminate\Database\Eloquent\ModelNotFoundException;
13
14
class KeyFobAccess
15
{
16
17
    /**
18
     * The key fob string
19
     * @var string
20
     */
21
    protected  $keyFobId;
22
23
    /**
24
     * The key fob record
25
     * @var KeyFob
26
     */
27
    protected $keyFob;
28
29
    /**
30
     * The key for the selected device
31
     * @var string
32
     */
33
    protected $deviceKey;
34
35
    /**
36
     * The selected device record
37
     * The device that's being acted apon
38
     * @var
39
     */
40
    protected $device;
41
42
    /**
43
     * The action of the current session
44
     * @var string
45
     */
46
    protected $action;
47
48
    /**
49
     * @var User
50
     */
51
    protected $user;
52
53
    /**
54
     * @var ActivityRepository
55
     */
56
    protected $activityRepository;
57
58
59
    protected $messageDelayed = false;
60
61
62
    protected $memberName;
63
64
    /**
65
     * @var Carbon
66
     */
67
    protected $time;
68
    /**
69
     * @var EquipmentRepository
70
     */
71
    private $equipmentRepository;
72
    /**
73
     * @var InductionRepository
74
     */
75
    private $inductionRepository;
76
    /**
77
     * @var Credit
78
     */
79
    private $bbCredit;
80
81
82 View Code Duplication
    public function __construct(ActivityRepository $activityRepository, EquipmentRepository $equipmentRepository, InductionRepository $inductionRepository, Credit $bbCredit)
83
    {
84
        $this->activityRepository = $activityRepository;
85
        $this->equipmentRepository = $equipmentRepository;
86
        $this->inductionRepository = $inductionRepository;
87
        $this->bbCredit = $bbCredit;
88
    }
89
90
91
    /**
92
     * @param string $keyFobId
93
     */
94
    public function setKeyFobId($keyFobId)
95
    {
96
        $this->keyFobId = $keyFobId;
97
    }
98
99
    /**
100
     * @param string $deviceKey
101
     */
102
    public function setDeviceKey($deviceKey)
103
    {
104
        $this->deviceKey = $deviceKey;
105
    }
106
107
    /**
108
     * @param string $action
109
     */
110
    public function setAction($action)
111
    {
112
        $this->action = $action;
113
    }
114
115
    /**
116
     * @return string
117
     */
118
    public function getKeyFobId()
119
    {
120
        return $this->keyFobId;
121
    }
122
123
    /**
124
     * @return
125
     */
126
    public function getKeyFob()
127
    {
128
        return $this->keyFob;
129
    }
130
131
    /**
132
     * @return string
133
     */
134
    public function getDeviceKey()
135
    {
136
        return $this->deviceKey;
137
    }
138
139
    /**
140
     * @return string
141
     */
142
    public function getAction()
143
    {
144
        return $this->action;
145
    }
146
147
    /**
148
     * @return User
149
     */
150
    public function getUser()
151
    {
152
        return $this->user;
153
    }
154
155
    /**
156
     * Check a fob id is valid for door entry and return the member if it is
157
     * @param $keyId
158
     * @param string $doorName
159
     * @param $time
160
     * @return \User
161
     * @throws ValidationException
162
     */
163
    public function verifyForEntry($keyId, $doorName, $time)
164
    {
165
        $this->keyFob = $this->lookupKeyFob($keyId);
166
167
        $this->setAccessTime($time);
168
169
        //Make sure the user is active
170
        $this->user = $this->keyFob->user;
171
        if ( ! $this->user || ! $this->user->active) {
172
            $this->logFailure();
173
            throw new ValidationException('Not a member');
174
        }
175
176
        if ( ! $this->user->trusted) {
177
            $this->logFailure();
178
            throw new ValidationException('Not a keyholder');
179
        }
180
181
        if ( ! $this->user->key_holder) {
182
            $this->logFailure();
183
            throw new ValidationException('Not a keyholder');
184
        }
185
186 View Code Duplication
        if ( ! ($this->user->profile->profile_photo || $this->user->profile->profile_photo_on_wall)) {
187
            $this->logFailure();
188
            throw new ValidationException('Member not trusted');
189
        }
190
191
        $this->memberName = $this->user->given_name;
192
193
194
        //Fetch any commands that need to be returned to the device
195
196
        return $this->keyFob->user;
197
    }
198
199
200
    public function verifyForDevice($keyId, $device, $time)
201
    {
202
        $this->keyFob = $this->lookupKeyFob($keyId);
203
        $this->setAccessTime($time);
204
205
        //Make sure the user is active
206
        $this->user = $this->keyFob->user;
207
        if ( ! $this->user || ! $this->user->active) {
208
            $this->logFailure();
209
            throw new ValidationException('Not a member');
210
        }
211
212
        //Validate the device
213
        try {
214
            /** @var Equipment $device */
215
            $device = $this->equipmentRepository->findBySlug($device);
216
        } catch (ModelNotFoundException $e) {
217
            throw new ValidationException('Invalid Device Key');
218
        }
219
220
        //Make sure the user is allowed to use the device
221
        if ($device->requires_induction) {
0 ignored issues
show
Documentation introduced by
The property requires_induction does not exist on object<BB\Entities\Equipment>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
222
            //Verify the user has training
223
            if ( ! $this->inductionRepository->isUserTrained($this->user->id, $device)) {
224
                throw new ValidationException('User Not Trained');
225
            }
226
        }
227
228
229
        //Make sure the member has enough money on their account
230
        $minimumBalance = $this->bbCredit->acceptableNegativeBalance('equipment-fee');
231
        if (($this->user->cash_balance + ($minimumBalance * 100)) <= 0) {
232
            throw new ValidationException('User doesn\'t have enough credit');
233
        }
234
235
        return $this->user;
236
    }
237
238 View Code Duplication
    public function lookupKeyFob($keyId)
239
    {
240
        try {
241
            $keyFob = KeyFob::lookup($keyId);
242
            return $keyFob;
243
        } catch (\Exception $e) {
244
            $keyId = substr('BB' . $keyId, 0, 12);
245
            try {
246
                $keyFob = KeyFob::lookup($keyId);
247
            } catch (\Exception $e) {
248
                throw new ValidationException('Key fob ID not valid');
249
            }
250
            return $keyFob;
251
        }
252
    }
253
254
255
    /**
256
     * @param $keyId
257
     *
258
     * @return KeyFob
259
     */
260
    public function extendedKeyFobLookup($keyId)
261
    {
262
        try {
263
            $keyFob = KeyFob::lookup($keyId);
264
        } catch (\Exception $e) {
265
            $oldTagId = substr('BB' . $keyId, 0, 12);
266
            try {
267
                $keyFob = KeyFob::lookup($oldTagId);
268
            } catch (\Exception $e) {
269
270
                //The ids coming in will have no checksum (last 2 digits) and the first digit will be incorrect
271
272
                //Remove the first character
273
                $keyId = substr($keyId, 1);
274
275
                try {
276
                    $keyFob = KeyFob::lookupPartialTag($keyId);
277
                } catch (\Exception $e) {
278
                    throw new ModelNotFoundException('Key fob ID not found');
279
                }
280
            }
281
        }
282
        return $keyFob;
283
    }
284
285
    public function logFailure()
286
    {
287
        $log               = [];
288
        $log['key_fob_id'] = $this->keyFob->id;
289
        $log['user_id']    = $this->user->id;
290
        $log['service']    = 'main-door';
291
        $log['delayed']    = $this->messageDelayed;
292
        $log['response']   = 402;
293
        $log['created_at'] = $this->time;
294
        $this->activityRepository->logAccessAttempt($log);
295
296
    }
297
298
    public function logSuccess()
299
    {
300
        event(new MemberActivity($this->keyFob, 'main-door', $this->time, $this->messageDelayed));
301
302
        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
303
        $activity = $this->activityRepository->recordMemberActivity($this->user->id, $this->keyFob->id, 'main-door', $this->time);
304
305
        if ($this->messageDelayed) {
306
            $activity->delayed = true;
307
            $activity->save();
308
        }
309
        */
310
    }
311
312
    /**
313
     * @return mixed
314
     */
315
    public function getMemberName()
316
    {
317
        return $this->memberName;
318
    }
319
320
    /**
321
     * Set the time to a specific timestamp - the new entry system will be passing a local time with the requests
322
     * @param null $time
323
     */
324
    protected function setAccessTime($time = null)
325
    {
326
        if ( ! empty($time)) {
327
            $this->time = Carbon::createFromTimestamp($time);
328
            $this->messageDelayed = true;
329
        } else {
330
            $this->time = Carbon::now();
331
        }
332
    }
333
334
} 
335