Issues (55)

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/records/UserAssociation.php (1 issue)

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
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/organization/license
6
 * @link       https://www.flipboxfactory.com/software/organization/
7
 */
8
9
namespace flipbox\organizations\records;
10
11
use Craft;
12
use flipbox\craft\ember\helpers\ModelHelper;
13
use flipbox\craft\ember\records\ActiveRecord;
14
use flipbox\craft\ember\records\IdAttributeTrait;
15
use flipbox\craft\ember\records\SortableTrait;
16
use flipbox\craft\ember\records\UserAttributeTrait;
17
use flipbox\organizations\relationships\RelationshipInterface;
18
use flipbox\organizations\relationships\UserTypeRelationship;
19
use flipbox\organizations\Organizations;
20
use flipbox\organizations\queries\UserAssociationQuery;
21
use yii\db\ActiveQueryInterface;
22
use yii\helpers\Json;
23
24
/**
25
 * @author Flipbox Factory <[email protected]>
26
 * @since 1.0.0
27
 *
28
 * @property int $organizationId
29
 * @property int $organizationOrder The order which an organization lists its users
30
 * @property int $userOrder The order which a user lists its organizations
31
 * @property string $state The user state
32
 * @property Organization $organization
33
 * @property UserType[] $typeRecords
34
 */
35
class UserAssociation extends ActiveRecord
36
{
37
38
    const STATE_ACTIVE = 'active';
39
    const STATE_PENDING = 'pending';
40
    const STATE_INACTIVE = 'inactive';
41
    const STATE_INVITED = 'invited';
42
43
    use SortableTrait,
44
        UserAttributeTrait,
45
        IdAttributeTrait,
46
        OrganizationAttributeTrait;
47
48
    /**
49
     * The table name
50
     */
51
    const TABLE_ALIAS = Organization::TABLE_ALIAS . '_user_associations';
52
53
    /**
54
     * Whether associated types should be saved
55
     *
56
     * @var bool
57
     */
58
    private $saveTypes = true;
59
60
    /**
61
     * @inheritdoc
62
     */
63
    protected $getterPriorityAttributes = ['userId', 'organizationId'];
64
65
    /**
66
     * @var RelationshipInterface
67
     */
68
    private $manager;
69
70
    /**
71
     * @return static
72
     */
73
    public function withTypes(): self
74
    {
75
        $this->saveTypes = true;
76
        return $this;
77
    }
78
79
    /**
80
     * @return static
81
     */
82
    public function withoutTypes(): self
83
    {
84
        $this->saveTypes = false;
85
        return $this;
86
    }
87
88
    /**
89
     * @inheritdoc
90
     */
91
    public function init()
92
    {
93
        parent::init();
94
95
        // Default state
96
        if (empty($this->state)) {
97
            $this->state = Organizations::getInstance()->getSettings()->getDefaultUserState();
98
        }
99
    }
100
101
    /**
102
     * @noinspection PhpDocMissingThrowsInspection
103
     *
104
     * @inheritdoc
105
     * @return UserAssociationQuery
106
     */
107
    public static function find()
108
    {
109
        /** @noinspection PhpUnhandledExceptionInspection */
110
        /** @noinspection PhpIncompatibleReturnTypeInspection */
111
        return Craft::createObject(UserAssociationQuery::class, [get_called_class()]);
112
    }
113
114
    /**
115
     * @return array
116
     */
117
    public function rules()
118
    {
119
        return array_merge(
120
            parent::rules(),
121
            $this->idRules(),
122
            $this->userRules(),
123
            $this->organizationRules(),
124
            [
125
                [
126
                    [
127
                        'userId',
128
                        'organizationId',
129
                        'state'
130
                    ],
131
                    'required'
132
                ],
133
                [
134
                    [
135
                        'state'
136
                    ],
137
                    'in',
138
                    'range' => array_keys(Organizations::getInstance()->getSettings()->getUserStates())
139
                ],
140
                [
141
                    [
142
                        'state'
143
                    ],
144
                    'default',
145
                    'value' => Organizations::getInstance()->getSettings()->getDefaultUserState()
146
                ],
147
                [
148
                    [
149
                        'userOrder',
150
                        'organizationOrder'
151
                    ],
152
                    'number',
153
                    'integerOnly' => true
154
                ],
155
                [
156
                    [
157
                        'userId',
158
                        'organizationId'
159
                    ],
160
                    'safe',
161
                    'on' => [
162
                        ModelHelper::SCENARIO_DEFAULT
0 ignored issues
show
Deprecated Code introduced by
The constant flipbox\craft\ember\help...elper::SCENARIO_DEFAULT has been deprecated with message: Use `yii\base\Model::SCENARIO_DEFAULT`

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
163
                    ]
164
                ]
165
            ]
166
        );
167
    }
168
169
    /**
170
     * @inheritdoc
171
     */
172
    public function beforeSave($insert)
173
    {
174
        if (Organizations::getInstance()->getSettings()->getEnforceUserSortOrder()) {
175
            $this->ensureSortOrder(
176
                [
177
                    'userId' => $this->userId
178
                ],
179
                'organizationOrder'
180
            );
181
        }
182
183
        if (Organizations::getInstance()->getSettings()->getEnforceOrganizationSortOrder()) {
184
            $this->ensureSortOrder(
185
                [
186
                    'organizationId' => $this->organizationId
187
                ],
188
                'userOrder'
189
            );
190
        }
191
192
        return parent::beforeSave($insert);
193
    }
194
195
    /**
196
     * @inheritdoc
197
     * @throws \yii\db\Exception
198
     */
199
    public function afterSave($insert, $changedAttributes)
200
    {
201
        try {
202
            if (Organizations::getInstance()->getSettings()->getEnforceUserSortOrder()) {
203
                $this->autoReOrder(
204
                    'userId',
205
                    [
206
                        'organizationId' => $this->organizationId
207
                    ],
208
                    'userOrder'
209
                );
210
            }
211
212
            if (Organizations::getInstance()->getSettings()->getEnforceOrganizationSortOrder()) {
213
                $this->autoReOrder(
214
                    'organizationId',
215
                    [
216
                        'userId' => $this->userId
217
                    ],
218
                    'organizationOrder'
219
                );
220
            }
221
        } catch (\Exception $e) {
222
            Organizations::error(
223
                sprintf(
224
                    "Exception caught while trying to reorder '%s'. Exception: [%s].",
225
                    (string)get_class($this),
226
                    (string)Json::encode([
227
                        'Trace' => $e->getTraceAsString(),
228
                        'File' => $e->getFile(),
229
                        'Line' => $e->getLine(),
230
                        'Code' => $e->getCode(),
231
                        'Message' => $e->getMessage()
232
                    ])
233
                ),
234
                __METHOD__
235
            );
236
        }
237
238
        // Save types if they've also been altered
239
        if (true === $this->saveTypes && $this->getTypes()->isMutated()) {
240
            $this->getTypes()->save();
241
        }
242
243
        parent::afterSave($insert, $changedAttributes);
244
    }
245
246
    /**
247
     * @inheritdoc
248
     * @throws \yii\db\Exception
249
     */
250
    public function afterDelete()
251
    {
252
        if (Organizations::getInstance()->getSettings()->getEnforceOrganizationSortOrder()) {
253
            $this->sequentialOrder(
254
                'organizationId',
255
                [
256
                    'userId' => $this->userId
257
                ],
258
                'organizationOrder'
259
            );
260
        }
261
262
        if (Organizations::getInstance()->getSettings()->getEnforceUserSortOrder()) {
263
            $this->sequentialOrder(
264
                'userId',
265
                [
266
                    'organizationId' => $this->organizationId
267
                ],
268
                'userOrder'
269
            );
270
        }
271
272
        parent::afterDelete();
273
    }
274
275
    /**
276
     * @return ActiveQueryInterface
277
     */
278
    public function getTypeRecords(): ActiveQueryInterface
279
    {
280
        /** @noinspection PhpUndefinedMethodInspection */
281
        return $this->hasMany(UserType::class, ['id' => 'typeId'])
282
            ->viaTable(
283
                UserTypeAssociation::tableName(),
284
                ['userId' => 'id']
285
            );
286
    }
287
288
    /**
289
     * @return UserTypeRelationship|RelationshipInterface
290
     */
291
    public function getTypes(): RelationshipInterface
292
    {
293
        if (null === $this->manager) {
294
            $this->manager = new UserTypeRelationship($this);
295
        }
296
297
        return $this->manager;
298
    }
299
300
301
    /************************************************************
302
     * RELATIONS
303
     ************************************************************/
304
305
    /**
306
     * We're using an alias so 'types' can be used to retrieve relations
307
     *
308
     * @inheritDoc
309
     */
310
    public function getRelation($name, $throwException = true)
311
    {
312
        if ($name === 'types') {
313
            $name = 'typeRecords';
314
        }
315
316
        return parent::getRelation($name);
317
    }
318
319
    /**
320
     * We're using an alias so 'types' is converted to 'typeRecords'
321
     *
322
     * @inheritDoc
323
     */
324
    public function populateRelation($name, $records)
325
    {
326
        if ($name === 'types') {
327
            $name = 'typeRecords';
328
        }
329
330
        parent::populateRelation($name, $records);
331
    }
332
}
333