Issues (38)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/controllers/BaseController.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Itstructure\UsersModule\controllers;
4
5
use Yii;
6
use yii\db\ActiveRecordInterface;
7
use yii\helpers\ArrayHelper;
8
use yii\filters\{VerbFilter, AccessControl};
9
use yii\base\UnknownMethodException;
10
use yii\web\{IdentityInterface, ConflictHttpException, BadRequestHttpException, NotFoundHttpException, Controller};
11
use Itstructure\UsersModule\Module;
12
use Itstructure\UsersModule\interfaces\{ModelInterface, ValidateComponentInterface};
13
14
/**
15
 * Class BaseController
16
 * Base controller class for the `users` module.
17
 *
18
 * @property Module $module
19
 * @property bool $viewCreated
20
 * @property array $additionFields
21
 * @property array $additionAttributes
22
 * @property string $urlPrefix Url prefix for redirect and view links.
23
 * @property ModelInterface $model
24
 * @property ActiveRecordInterface $searchModel
25
 * @property ValidateComponentInterface $validateComponent
26
 *
27
 * @package Itstructure\UsersModule\controllers
28
 */
29
abstract class BaseController extends Controller
30
{
31
    /**
32
     * Watch or not created record.
33
     *
34
     * @var bool
35
     */
36
    protected $viewCreated = false;
37
38
    /**
39
     * Addition fields for the template.
40
     *
41
     * @var array
42
     */
43
    protected $additionFields = [];
44
45
    /**
46
     * Addition attributes with values for the model.
47
     * [
48
     *    'key1' => 'value1',
49
     *    'key2' => 'value2',
50
     * ]
51
     *
52
     * @var array
53
     */
54
    protected $additionAttributes = [];
55
56
    /**
57
     * Url prefix for redirect and view links.
58
     * @var string
59
     */
60
    protected $urlPrefix = '';
61
62
    /**
63
     * Model object record.
64
     *
65
     * @var ModelInterface
66
     */
67
    private $model;
68
69
    /**
70
     * Search new model object.
71
     *
72
     * @var ActiveRecordInterface
73
     */
74
    private $searchModel;
75
76
    /**
77
     * Validate component.
78
     *
79
     * @var ValidateComponentInterface
80
     */
81
    private $validateComponent = null;
82
83
    /**
84
     * Returns the name of the base model.
85
     *
86
     * @return string
87
     */
88
    abstract protected function getModelName():string;
89
90
    /**
91
     * Returns the name of the model to search it.
92
     *
93
     * @return string
94
     */
95
    abstract protected function getSearchModelName():string;
96
97
    /**
98
     * @inheritdoc
99
     */
100
    public function behaviors()
101
    {
102
        return [
103
            'access' => [
104
                'class' => AccessControl::class,
105
                'rules' => [
106
                    [
107
                        'allow' => true,
108
                        'roles' => $this->module->accessRoles,
109
                    ],
110
                ],
111
            ],
112
            'verbs' => [
113
                'class' => VerbFilter::class,
114
                'actions' => [
115
                    'delete' => [
116
                        'POST',
117
                    ],
118
                ],
119
            ],
120
        ];
121
    }
122
123
    /**
124
     * Initializer.
125
     */
126
    public function init()
127
    {
128
        $this->view->params['user'] = Yii::$app->user->identity;
129
    }
130
131
    /**
132
     * @param \yii\base\Action $action
133
     * @return bool
134
     */
135
    public function beforeAction($action)
136
    {
137
        $this->view->params['urlPrefix'] = $this->urlPrefix;
138
139
        return parent::beforeAction($action);
140
    }
141
142
    /**
143
     * Give ability of configure view to the module class.
144
     *
145
     * @return \yii\base\View|\yii\web\View
146
     */
147
    public function getView()
148
    {
149
        if (method_exists($this->module, 'getView')) {
150
            return $this->module->getView();
151
        }
152
153
        return parent::getView();
154
    }
155
156
    /**
157
     * Set model.
158
     *
159
     * @param $model ModelInterface
160
     */
161
    public function setModel(ModelInterface $model): void
162
    {
163
        $this->model = $model;
0 ignored issues
show
Documentation Bug introduced by
It seems like $model of type object<Itstructure\Users...erfaces\ModelInterface> is incompatible with the declared type object<ModelInterface> of property $model.

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...
164
    }
165
166
    /**
167
     * Set search model.
168
     *
169
     * @param $model ActiveRecordInterface
170
     */
171
    public function setSearchModel(ActiveRecordInterface $model): void
172
    {
173
        $this->searchModel = $model;
174
    }
175
176
    /**
177
     * Set validate component for main model.
178
     *
179
     * @param $component ValidateComponentInterface
180
     */
181
    public function setValidateComponent(ValidateComponentInterface $component): void
182
    {
183
        $this->validateComponent = $component;
0 ignored issues
show
Documentation Bug introduced by
It seems like $component of type object<Itstructure\Users...dateComponentInterface> is incompatible with the declared type object<ValidateComponentInterface> of property $validateComponent.

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...
184
    }
185
186
    /**
187
     * Returns model.
188
     *
189
     * @return ModelInterface
190
     */
191
    public function getModel(): ModelInterface
192
    {
193
        return $this->model;
194
    }
195
196
    /**
197
     * Returns search model.
198
     *
199
     * @return ActiveRecordInterface
200
     */
201
    public function getSearchModel(): ActiveRecordInterface
202
    {
203
        return $this->searchModel;
204
    }
205
206
    /**
207
     * Get validate component for main model.
208
     *
209
     * @return ValidateComponentInterface
210
     */
211
    public function getValidateComponent(): ValidateComponentInterface
212
    {
213
        return $this->validateComponent;
214
    }
215
216
    /**
217
     * List of records.
218
     *
219
     * @return string
220
     */
221
    public function actionIndex()
222
    {
223
        $this->setSearchModel(
224
            $this->getNewSearchModel()
225
        );
226
227
        return $this->render('index',
228
            ArrayHelper::merge(
229
                [
230
                    'searchModel' => $this->searchModel,
231
                    'dataProvider' => $this->searchModel->search(Yii::$app->request->queryParams),
0 ignored issues
show
The method search() does not seem to exist on object<yii\db\ActiveRecordInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
232
                ],
233
                $this->getAdditionFields()
234
            )
235
        );
236
    }
237
238
    /**
239
     * Displays one model entry.
240
     *
241
     * @param int|string $id
242
     *
243
     * @return mixed
244
     */
245
    public function actionView($id)
246
    {
247
        return $this->render('view',
248
            ArrayHelper::merge(
249
                [
250
                    'model' => $this->findModel($id),
251
                ],
252
                $this->getAdditionFields()
253
            )
254
        );
255
    }
256
257
    /**
258
     * Creates a new model record.
259
     * If the result of creation is successful, there will be a redirect to the 'view' or 'index' page.
260
     *
261
     * @return string|\yii\web\Response
262
     */
263
    public function actionCreate()
264
    {
265
        $this->setModelByConditions();
266
267
        if (Yii::$app->request->isPost &&
268
            $this->model->load(Yii::$app->request->post()) &&
269
            $this->setAdditionAttributes() &&
270
            $this->model->save()) {
271
272
            if ($this->viewCreated) {
273
                $redirectParams = [
274
                    $this->urlPrefix.'view',
275
                    'id' => $this->model->getId(),
276
                ];
277
            } else {
278
                $redirectParams = [
279
                    $this->urlPrefix.'index',
280
                ];
281
            }
282
283
            return $this->redirect($redirectParams);
284
        }
285
286
        return $this->render('create',
287
            ArrayHelper::merge(
288
                [
289
                    'model' => $this->model,
290
                ],
291
                $this->getAdditionFields()
292
            )
293
        );
294
    }
295
296
    /**
297
     * Updates the current model entry.
298
     * If the result of creation is successful, there will be a redirect to the 'view' or 'index' page.
299
     *
300
     * @param int|string $id
301
     *
302
     * @return string|\yii\web\Response
303
     */
304
    public function actionUpdate($id)
305
    {
306
        $this->setModelByConditions($id);
307
308
        if (Yii::$app->request->isPost &&
309
            $this->model->load(Yii::$app->request->post()) &&
310
            $this->setAdditionAttributes() &&
311
            $this->model->save()) {
312
313
            return $this->redirect([
314
                $this->urlPrefix.'view',
315
                'id' => $this->model->getId(),
316
            ]);
317
        }
318
319
        return $this->render('update',
320
            ArrayHelper::merge(
321
                [
322
                    'model' => $this->model,
323
                ],
324
                $this->getAdditionFields()
325
            )
326
        );
327
    }
328
329
    /**
330
     * Deletes the current model entry.
331
     * If the result of the deletion is successful, there will be a redirect to the 'index' page.
332
     *
333
     * @param int|string $id
334
     *
335
     * @return \yii\web\Response
336
     *
337
     * @throws ConflictHttpException
338
     */
339
    public function actionDelete($id)
340
    {
341
        $model = $this->findModel($id);
342
343
        if ($model instanceof IdentityInterface && $id == Yii::$app->user->identity->getId()) {
344
            throw new ConflictHttpException('You can not delete yourself.');
345
        };
346
347
        $model->delete();
348
349
        return $this->redirect(['index']);
350
    }
351
352
    /**
353
     * Set addition attributes for model.
354
     *
355
     * @return bool
356
     */
357
    protected function setAdditionAttributes(): bool
358
    {
359
        $this->model->setAttributes($this->additionAttributes, false);
360
361
        return true;
362
    }
363
364
    /**
365
     * Get addition fields for the view template.
366
     * @return array
367
     */
368
    protected function getAdditionFields(): array
369
    {
370
        return $this->additionFields;
371
    }
372
373
    /**
374
     * Returns new object of main model.
375
     *
376
     * @return mixed
377
     */
378
    protected function getNewModel()
379
    {
380
        $modelName = $this->getModelName();
381
        return new $modelName;
382
    }
383
384
    /**
385
     * Returns new object of search main model.
386
     *
387
     * @return mixed
388
     */
389
    protected function getNewSearchModel()
390
    {
391
        $searchModelName = $this->getSearchModelName();
392
        return new $searchModelName;
393
    }
394
395
    /**
396
     * Find model record.
397
     * If the model is not found, a 404 HTTP exception will be displayed.
398
     *
399
     * @param int|string $key
400
     *
401
     *
402
     * @throws BadRequestHttpException
403
     * @throws UnknownMethodException
404
     * @throws NotFoundHttpException
405
     *
406
     * @return mixed
407
     */
408
    private function findModel($key)
409
    {
410
        if (null === $key){
411
            throw new BadRequestHttpException('Key parameter is not defined in findModel method.');
412
        }
413
414
        $modelObject = $this->getNewModel();
415
416 View Code Duplication
        if (!method_exists($modelObject, 'findOne')){
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
417
            $class = (new\ReflectionClass($modelObject));
418
            throw new UnknownMethodException('Method findOne does not exists in ' . $class->getNamespaceName() . '\\' . $class->getShortName().' class.');
419
        }
420
421
        $result = call_user_func([
422
            $modelObject,
423
            'findOne',
424
        ], $key);
425
426
        if ($result !== null) {
427
            return $result;
428
        }
429
430
        throw new NotFoundHttpException('The requested page does not exist.');
431
    }
432
433
    /**
434
     * Returns an intermediate model for working with the main.
435
     *
436
     * @param int|string|null $key
437
     *
438
     * @return void
439
     */
440
    private function setModelByConditions($key = null): void
441
    {
442
        $model = null === $key ? $this->getNewModel() : $this->findModel($key);
443
444
        if (null === $this->validateComponent){
445
            $this->setModel($model);
446
        } else {
447
            $this->setModel(
448
                $this->validateComponent->setModel($model)
449
            );
450
        }
451
    }
452
}