Passed
Push — master ( e6c475...db71b9 )
by Darío
04:47
created

SingUp::getUsersEntity()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Auth\Controller;
4
5
use Auth\Model\User;
6
use Auth\Model\UserTbl;
7
use Drone\Db\TableGateway\EntityAdapter;
8
use Drone\Debug\Catcher;
0 ignored issues
show
Bug introduced by
The type Drone\Debug\Catcher was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Drone\Dom\Element\Form;
10
use Drone\Mvc\AbstractionController;
11
use Drone\Network\Http;
12
use Drone\Validator\FormValidator;
13
use Zend\Crypt\Password\Bcrypt;
14
use Drone\Error\Errno;
15
16
class SingUp extends AbstractionController
17
{
18
    use \Drone\Error\ErrorTrait;
19
20
    /**
21
     * @var UsersEntity
0 ignored issues
show
Bug introduced by
The type Auth\Controller\UsersEntity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
     */
23
    private $usersEntity;
24
25
    /**
26
     * @return UsersEntity
27
     */
28
    private function getUsersEntity()
29
    {
30
        if (!is_null($this->usersEntity))
31
            return $this->usersEntity;
32
33
        $this->usersEntity = new EntityAdapter(new UserTbl(new User()));
0 ignored issues
show
Documentation Bug introduced by
It seems like new Drone\Db\TableGatewa...new Auth\Model\User())) of type Drone\Db\TableGateway\EntityAdapter is incompatible with the declared type Auth\Controller\UsersEntity of property $usersEntity.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
34
35
        return $this->usersEntity;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->usersEntity returns the type Drone\Db\TableGateway\EntityAdapter which is incompatible with the documented return type Auth\Controller\UsersEntity.
Loading history...
36
    }
37
38
    /**
39
     * Checks user session and redirect to other module if exists any active session
40
     *
41
     * @return null
42
     */
43
    private function checkSession()
44
    {
45
        $config = include 'module/Auth/config/user.config.php';
46
        $method = $config["authentication"]["method"];
47
        $key    = $config["authentication"]["key"];
48
49
        switch ($method)
50
        {
51
            case '_COOKIE':
52
53
                if (array_key_exists($key, $_COOKIE) || !empty($_COOKIE[$key]))
54
                {
55
                    if (array_key_exists("CR_VAR_URL_REJECTED", $_SESSION) || !empty($_SESSION["CR_VAR_URL_REJECTED"]))
56
                        header("location: " . $_SESSION["CR_VAR_URL_REJECTED"]);
57
                    else
58
                        header("location: " . $this->basePath . "/public/" . $config["redirect"]);
0 ignored issues
show
Bug introduced by
The property basePath is declared private in Drone\Mvc\AbstractionController and cannot be accessed from this context.
Loading history...
59
                }
60
61
                break;
62
63
            case '_SESSION':
64
65
                if (array_key_exists($key, $_SESSION) || !empty($_SESSION[$key]))
66
                {
67
                    if (array_key_exists("CR_VAR_URL_REJECTED", $_SESSION) || !empty($_SESSION["CR_VAR_URL_REJECTED"]))
68
                        header("location: " . $_SESSION["CR_VAR_URL_REJECTED"]);
69
                    else
70
                        header("location: " . $this->basePath . "/public/" . $config["redirect"]);
71
                }
72
73
                break;
74
        }
75
    }
76
77
    /**
78
     * Shows register form
79
     *
80
     * @return array
81
     */
82
    public function index()
83
    {
84
        # STANDARD VALIDATIONS [check method]
85
        if (!$this->isGet())
86
        {
87
            $http = new Http();
88
            $http->writeStatus($http::HTTP_METHOD_NOT_ALLOWED);
89
90
            die('Error ' . $http::HTTP_METHOD_NOT_ALLOWED .' (' . $http->getStatusText($http::HTTP_METHOD_NOT_ALLOWED) . ')!!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
91
        }
92
93
        $this->checkSession();
94
95
        return [];
96
    }
97
98
    /**
99
     * Does register process
100
     *
101
     * @return array
102
     */
103
    public function attemp()
104
    {
105
        # data to send
106
        $data = [];
107
108
        # environment settings
109
        $post = $this->getPost();           # catch $_POST
110
        $this->setTerminal(true);           # set terminal
111
112
        # TRY-CATCH-BLOCK
113
        try {
114
115
            # STANDARD VALIDATIONS [check method]
116
            if (!$this->isPost())
117
            {
118
                $http = new Http();
119
                $http->writeStatus($http::HTTP_METHOD_NOT_ALLOWED);
120
121
                die('Error ' . $http::HTTP_METHOD_NOT_ALLOWED .' (' . $http->getStatusText($http::HTTP_METHOD_NOT_ALLOWED) . ')!!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
122
            }
123
124
            # STANDARD VALIDATIONS [check needed arguments]
125
            $needles = ['username', 'email', 'password', 'password_confirm'];
126
127
            array_walk($needles, function(&$item) use ($post) {
128
                if (!array_key_exists($item, $post))
129
                {
130
                    $http = new Http();
131
                    $http->writeStatus($http::HTTP_BAD_REQUEST);
132
133
                    die('Error ' . $http::HTTP_BAD_REQUEST .' (' . $http->getStatusText($http::HTTP_BAD_REQUEST) . ')!!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
134
                }
135
            });
136
137
            $this->checkSession();
138
139
            if ($post["password"] !== $post["password_confirm"])
140
                throw new \Drone\Exception\Exception("The password fields are different!", 300);
141
142
            $components = [
143
                "attributes" => [
144
                    "username" => [
145
                        "required"  => true,
146
                        "type"      => "text",
147
                        "minlength" => 4,
148
                        "maxlength" => 20
149
                    ],
150
                    "email" => [
151
                        "required"  => true,
152
                        "type"      => "text",
153
                        "minlength" => 4,
154
                        "maxlength" => 50
155
                    ],
156
                    "password" => [
157
                        "required"  => true,
158
                        "type"      => "text",
159
                        "minlength" => 4,
160
                        "maxlength" => 20
161
                    ],
162
                    "password_confirm" => [
163
                        "required"  => true,
164
                        "type"      => "text",
165
                        "minlength" => 4,
166
                        "maxlength" => 20
167
                    ]
168
                ],
169
            ];
170
171
            $options = [
172
                "username" => [
173
                    "label"      => "Username",
174
                    "validators" => [
175
                        "Alnum"  => ["allowWhiteSpace" => false]
176
                    ]
177
                ],
178
                "email" => [
179
                    "label"      => "Email"
180
                ],
181
                "password" => [
182
                    "label"      => "Password"
183
                ],
184
                "password_confirm" => [
185
                    "label"      => "Password confirmation"
186
                ]
187
            ];
188
189
            $form = new Form($components);
190
            $form->fill($post);
191
192
            $validator = new FormValidator($form, $options);
193
            $validator->validate();
194
195
            $data["validator"] = $validator;
196
197
            # STANDARD VALIDATIONS [check argument constraints]
198
            if (!$validator->isValid())
199
            {
200
                $data["messages"] = $validator->getMessages();
201
                throw new \Drone\Exception\Exception("Form validation errors!", 300);
202
            }
203
204
            $row = $this->getUsersEntity()->select([
205
                "USERNAME" => $post["username"]
206
            ]);
207
208
            if (count($row))
209
                throw new \Drone\Exception\Exception("This username already exists!", 300);
210
211
            $bcrypt = new Bcrypt();
212
            $securePass = $bcrypt->create($post["password"]);
213
214
            $t = base64_encode(time() . uniqid());
215
            $token = substr($t, 0, 30);
216
217
            $this->getUsersEntity()->getTableGateway()->getDriver()->getDb()->beginTransaction();
218
219
            $config = include 'module/Auth/config/user.config.php';
220
221
            $user = new User();
222
223
            $user->exchangeArray([
224
                "USER_ID"       => $this->getUsersEntity()->getTableGateway()->getNextId(),
225
                "USER_STATE_ID" => ($config["mail"]["checking"]["enabled"]) ? 1 : 2,
226
                "USERNAME"      => $post["username"],
227
                "EMAIL"         => $post["email"],
228
                "TOKEN"         => $token,
229
                "USER_PASSWORD" => $securePass
230
            ]);
231
232
            $this->getUsersEntity()->insert($user);
233
234
            $link = $_SERVER["HTTP_HOST"] . $this->basePath . "/public/Auth/SingUp/verifyEmail/user/" . $post["username"] . "/token/" . $token;
0 ignored issues
show
Bug introduced by
The property basePath is declared private in Drone\Mvc\AbstractionController and cannot be accessed from this context.
Loading history...
235
236
            $data["mail"] = ($config["mail"]["checking"]["enabled"]) ? true : false;
237
238
            if ($config["mail"]["checking"]["enabled"])
239
            {
240
                $from = $config["mail"]["checking"]["from"];
241
242
                $headers  = 'MIME-Version: 1.0' . "\r\n";
243
                $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
244
                $headers .= 'From: '. $from ."\r\n". 'X-Mailer: PHP/' . phpversion();
245
246
                if (!@mail(
247
                    $post["email"], "Email checking!",
248
                    "Your account has been registered!. Please click on the following link to confirm your account<br /><br />
249
                    <a href='$link'>$token</a>.",
250
                    $headers
251
                ))
252
                {
253
                    $this->getUsersEntity()->getTableGateway()->getDriver()->getDb()->rollback();
254
                    throw new \Exception("Error trying to send email checking. Try it again later!.");
255
                }
256
            }
257
258
            $this->getUsersEntity()->getTableGateway()->getDriver()->getDb()->endTransaction();
259
260
            $data["username"] = $post["username"];
261
            $data["email"] = $post["email"];
262
263
            # SUCCESS-MESSAGE
264
            $data["process"] = "success";
265
        }
266
        catch (\Drone\Exception\Exception $e)
267
        {
268
            # ERROR-MESSAGE
269
            $data["process"] = "warning";
270
            $data["message"] = $e->getMessage();
271
        }
272
        catch (\Exception $e)
273
        {
274
            $file = str_replace('\\', '', __CLASS__);
275
            $storage = new \Drone\Exception\Storage("cache/$file.json");
276
277
            # stores the error code
278
            if (($errorCode = $storage->store($e)) === false)
0 ignored issues
show
introduced by
The condition $errorCode = $storage->store($e) === false is always true.
Loading history...
279
            {
280
                $errors = $storage->getErrors();
281
282
                # if error storing is not possible, handle it (internal app error)
283
                $this->handleErrors($errors, __METHOD__);
284
            }
285
286
            # errors retrived by the use of ErrorTrait
287
            if (count($this->getErrors()))
288
                $this->handleErrors($this->getErrors(), __METHOD__);
289
290
            $data["code"]    = $errorCode;
291
            $data["message"] = $e->getMessage();
292
293
            $config = include 'config/application.config.php';
294
            $data["dev_mode"] = $config["environment"]["dev_mode"];
295
296
            # redirect view
297
            $this->setMethod('error');
298
299
            return $data;
300
        }
301
302
        return $data;
303
    }
304
305
    /**
306
     * Does email checking
307
     *
308
     * @return array
309
     */
310
    public function verifyEmail()
311
    {
312
        # data to send
313
        $data = [];
314
315
        # TRY-CATCH-BLOCK
316
        try {
317
318
            # STANDARD VALIDATIONS [check method]
319
            if (!$this->isGet())
320
            {
321
                $http = new Http();
322
                $http->writeStatus($http::HTTP_METHOD_NOT_ALLOWED);
323
324
                die('Error ' . $http::HTTP_METHOD_NOT_ALLOWED .' (' . $http->getStatusText($http::HTTP_METHOD_NOT_ALLOWED) . ')!!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
325
            }
326
327
            # STANDARD VALIDATIONS [check needed arguments]
328
            $needles = ['token', 'user'];
329
330
            array_walk($needles, function($item) {
331
                if (!array_key_exists($item, $_GET))
332
                {
333
                    $http = new Http();
334
                    $http->writeStatus($http::HTTP_BAD_REQUEST);
335
336
                    die('Error ' . $http::HTTP_BAD_REQUEST .' (' . $http->getStatusText($http::HTTP_BAD_REQUEST) . ')!!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
337
                }
338
            });
339
340
            # catch arguments
341
            $token = $_GET["token"];
342
            $user  = $_GET["user"];
343
344
            $row = $this->getUsersEntity()->select([
345
                "USERNAME" => $user,
346
                "TOKEN"    => $token
347
            ]);
348
349
            if (!count($row))
350
                throw new \Drone\Exception\Exception("Token has expired or username does not exists!.");
351
352
            $user = array_shift($row);
353
354
            if ($user->USER_STATE_ID <> 1)
355
                throw new \Drone\Exception\Exception("This email address had verified before!.", 300);
356
357
            $user->USER_STATE_ID = 2;
358
359
            $this->getUsersEntity()->update($user, [
360
                "USER_ID" => $user->USER_ID
361
            ]);
362
363
            # SUCCESS-MESSAGE
364
            $data["process"] = "success";
365
        }
366
        catch (\Drone\Exception\Exception $e)
367
        {
368
            # ERROR-MESSAGE
369
            $data["process"] = "warning";
370
            $data["message"] = $e->getMessage();
371
        }
372
        catch (\Exception $e)
373
        {
374
            $file = str_replace('\\', '', __CLASS__);
375
            $storage = new \Drone\Exception\Storage("cache/$file.json");
376
377
            # stores the error code
378
            if (($errorCode = $storage->store($e)) === false)
0 ignored issues
show
introduced by
The condition $errorCode = $storage->store($e) === false is always true.
Loading history...
379
            {
380
                $errors = $storage->getErrors();
381
382
                # if error storing is not possible, handle it (internal app error)
383
                $this->handleErrors($errors, __METHOD__);
384
            }
385
386
            # errors retrived by the use of ErrorTrait
387
            if (count($this->getErrors()))
388
                $this->handleErrors($this->getErrors(), __METHOD__);
389
390
            $data["code"]    = $errorCode;
391
            $data["message"] = $e->getMessage();
392
393
            $config = include 'config/application.config.php';
394
            $data["dev_mode"] = $config["environment"]["dev_mode"];
395
396
            # redirect view
397
            $this->setMethod('error');
398
399
            return $data;
400
        }
401
402
        return $data;
403
    }
404
405
    private function handleErrors(Array $errors, $method)
406
    {
407
        if (count($errors))
408
        {
409
            $errorInformation = "";
410
411
            foreach ($errors as $errno => $error)
412
            {
413
                $errorInformation .=
414
                    "<strong style='color: #a94442'>".
415
                        $method
416
                            . "</strong>: <span style='color: #e24f4c'>{$error}</span> \n<br />";
417
            }
418
419
            $hd = @fopen('cache/errors.txt', "a");
420
421
            if (!$hd || !@fwrite($hd, $errorInformation))
0 ignored issues
show
introduced by
$hd is of type resource|false, thus it always evaluated to false.
Loading history...
422
            {
423
                # error storing are not mandatory!
424
            }
425
            else
426
                @fclose($hd);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fclose(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

426
                /** @scrutinizer ignore-unhandled */ @fclose($hd);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
427
428
            $config = include 'config/application.config.php';
429
            $dev = $config["environment"]["dev_mode"];
430
431
            if ($dev)
432
                echo $errorInformation;
433
        }
434
    }
435
}