GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (4873)

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/common/project/UGroupManager.class.php (2 issues)

Labels
Severity

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
 * Copyright (c) Enalean, 2011 - 2015. All Rights Reserved.
4
 *
5
 * This file is a part of Tuleap.
6
 *
7
 * Tuleap is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * Tuleap is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with Tuleap; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21
22
require_once('www/project/admin/ugroup_utils.php');
23
require_once('www/include/account.php');
24
25
class UGroupManager {
26
    
27
    /**
28
     * @var UGroupDao
29
     */
30
    private $dao;
31
32
    /**
33
     * @var EventManager
34
     */
35
    private $event_manager;
36
37
    public function __construct(UGroupDao $dao = null, EventManager $event_manager = null) {
38
        $this->dao           = $dao;
39
        $this->event_manager = $event_manager;
40
    }
41
42
    /**
43
     *
44
     * @param Project $project
45
     * @param type $ugroup_id
46
     *
47
     * @return ProjectUGroup
48
     */
49
    public function getUGroupWithMembers(Project $project, $ugroup_id) {
50
        $ugroup = $this->getUGroup($project, $ugroup_id);
51
        $ugroup->getMembers();
52
53
        return $ugroup;
54
    }
55
56
    /**
57
     * @return ProjectUGroup of the given project or null if not found
58
     */
59
    public function getUGroup(Project $project, $ugroup_id) {
60
        $project_id = $project->getID();
61
        if ($ugroup_id <= 100) {
62
            $project_id = 100;
63
        }
64
65
        $row = $this->getDao()->searchByGroupIdAndUGroupId($project_id, $ugroup_id)->getRow();
66
        if ($row) {
67
            return $this->instanciateGroupForProject($project, $row);
68
        }
69
    }
70
71
    private function instanciateGroupForProject(Project $project, array $row) {
72
        // force group_id as it is set to 100 for dynamic groups
73
        $row['group_id'] = $project->getID();
74
        return new ProjectUGroup($row);
75
    }
76
77
    /**
78
     *
79
     * @param Project $project
80
     * @param array $excluded_ugroups_id
81
     * @return ProjectUGroup[]
82
     */
83
    public function getUGroups(Project $project, array $excluded_ugroups_id = array()) {
84
        $ugroups = array();
85
        foreach ($this->getDao()->searchDynamicAndStaticByGroupId($project->getId()) as $row) {
0 ignored issues
show
The expression $this->getDao()->searchD...upId($project->getId()) of type false|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
86
            if (in_array($row['ugroup_id'], $excluded_ugroups_id)) {
87
                continue;
88
            }
89
            $ugroups[] = $this->instanciateGroupForProject($project, $row);
90
        }
91
        return $ugroups;
92
    }
93
94
    /**
95
     * @return ProjectUGroup[]
96
     */
97
    public function getStaticUGroups(Project $project) {
98
        $ugroups = array();
99
        foreach ($this->getDao()->searchStaticByGroupId($project->getId()) as $row) {
0 ignored issues
show
The expression $this->getDao()->searchS...upId($project->getId()) of type false|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
100
            $ugroups[] = $this->instanciateGroupForProject($project, $row);
101
        }
102
        return $ugroups;
103
    }
104
105
    /**
106
     * @return ProjectUGroup
107
     */
108
    public function getUGroupByName(Project $project, $name) {
109
        $row = $this->getDao()->searchByGroupIdAndName($project->getID(), $name)->getRow();
110
        if (! $row && preg_match('/^ugroup_.*_key$/', $name)) {
111
            $row = $this->getDao()->searchByGroupIdAndName(100, $name)->getRow();
112
        }
113
        if (! $row && in_array($this->getUnormalisedName($name), User_ForgeUGroup::$names)) {
114
            $row = $this->getDao()->searchByGroupIdAndName(100, $this->getUnormalisedName($name))->getRow();
115
        }
116
        if (! $row && $ugroup = $this->getDynamicUGoupByName($project, $name)) {
117
            return $ugroup;
118
        }
119
        if ($row) {
120
            return new ProjectUGroup($row);
121
        }
122
        return null;
123
    }
124
125
    public function getDynamicUGoupIdByName($name) {
126
        return array_search($name, ProjectUGroup::$normalized_names);
127
    }
128
129
    public function getDynamicUGoupByName(Project $project, $name) {
130
        $ugroup_id = $this->getDynamicUGoupIdByName($name);
131
        if(empty($ugroup_id)) { return null; }
132
        return new ProjectUGroup(array(
133
            'ugroup_id' => $ugroup_id,
134
            'name'      => $name,
135
            'group_id'  => $project->getID()
136
        ));
137
    }
138
139
    private function getUnormalisedName($name) {
140
        return 'ugroup_'.$name.'_name_key';
141
    }
142
143
    public function getLabel($group_id, $ugroup_id) {
144
        $row = $this->getDao()->searchNameByGroupIdAndUGroupId($group_id, $ugroup_id)->getRow();
145
        if (! $row) {
146
            return '';
147
        }
148
149
        return $row['name'];
150
    }
151
152
    /**
153
     * Return all UGroups the user belongs to
154
     *
155
     * @param PFUser $user The user
156
     *
157
     * @return ProjectUGroup[]
158
     */
159
    public function getByUserId($user) {
160
        $ugroups = array();
161
        $dar     = $this->getDao()->searchByUserId($user->getId());
162
163
        if ($dar && ! $dar->isError()) {
164
            foreach ($dar as $row) {
165
                $ugroups [] = new ProjectUGroup($row);
166
            }
167
        }
168
169
        return $ugroups;
170
    }
171
172
    /**
173
     * Returns a ProjectUGroup from its Id
174
     *
175
     * @param Integer $ugroupId The UserGroupId
176
     * 
177
     * @return ProjectUGroup
178
     */
179
    public function getById($ugroupId) {
180
        $dar = $this->getDao()->searchByUGroupId($ugroupId);
181
        if ($dar && !$dar->isError() && $dar->rowCount() == 1) {
182
            return new ProjectUGroup($dar->getRow());
183
        } else {
184
            return new ProjectUGroup();
185
        }
186
    }
187
188
    /**
189
     * Wrapper for UGroupDao
190
     *
191
     * @return UGroupDao
192
     */
193
    public function getDao() {
194
        if (!$this->dao) {
195
            $this->dao = new UGroupDao();
196
        }
197
        return $this->dao;
198
    }
199
200
    /**
201
     * Wrapper for EventManager
202
     *
203
     * @return EventManager
204
     */
205
    private function getEventManager() {
206
        if (! $this->event_manager) {
207
            $this->event_manager = EventManager::instance();
208
        }
209
        return $this->event_manager;
210
    }
211
212
    /**
213
     * Get Dynamic ugroups members
214
     *
215
     * @param Integer $ugroupId Id of the ugroup
216
     * @param Integer $groupId  Id of the project
217
     *
218
     * @return array of User
219
     */
220
    public function getDynamicUGroupsMembers($ugroupId, $groupId) {
221
        if ($ugroupId > 100) {
222
            return array();
223
        }
224
        $um = UserManager::instance();
225
        $users   = array();
226
        $dao     = new UGroupUserDao();
227
        $members = $dao->searchUserByDynamicUGroupId($ugroupId, $groupId);
228
        if ($members && !$members->isError()) {
229
            foreach ($members as $member) {
230
                $users[] = $um->getUserById($member['user_id']);
231
            }
232
        }
233
        return $users;
234
    }
235
236
    /**
237
     * @param PFUSer $user
238
     * @param int $ugroup_id
239
     * @param int $group_id
240
     * @return boolean
241
     */
242
    public function isDynamicUGroupMember(PFUSer $user, $ugroup_id, $group_id) {
243
        $dao = new UGroupUserDao();
244
245
        return $dao->isDynamicUGroupMember($user->getId(), $ugroup_id, $group_id);
246
    }
247
248
    /**
249
     * Check if update users is allowed for a given user group
250
     *
251
     * @param Integer $ugroupId Id of the user group
252
     *
253
     * @return boolean
254
     */
255
    public function isUpdateUsersAllowed($ugroupId) {
256
        $ugroupUpdateUsersAllowed = true;
257
        $this->getEventManager()->processEvent(Event::UGROUP_UPDATE_USERS_ALLOWED, array('ugroup_id' => $ugroupId, 'allowed' => &$ugroupUpdateUsersAllowed));
258
        return $ugroupUpdateUsersAllowed;
259
    }
260
261
    /**
262
     * Wrapper for dao method that checks if the user group is valid
263
     *
264
     * @param Integer $groupId  Id of the project
265
     * @param Integer $ugroupId Id of the user goup
266
     *
267
     * @return boolean
268
     */
269
    public function checkUGroupValidityByGroupId($groupId, $ugroupId) {
270
        return $this->getDao()->checkUGroupValidityByGroupId($groupId, $ugroupId);
271
    }
272
273
    /**
274
     * Wrapper for dao method that retrieves all Ugroups bound to a given ProjectUGroup
275
     *
276
     * @param Integer $ugroupId Id of the user goup
277
     *
278
     * @return DataAccessResult
279
     */
280
    public function searchUGroupByBindingSource($ugroupId) {
281
        return $this->getDao()->searchUGroupByBindingSource($ugroupId);
282
    }
283
284
    /**
285
     * Wrapper for dao method that updates binding option for a given ProjectUGroup
286
     *
287
     * @param Integer $ugroup_id Id of the user group
288
     * @param Integer $source_ugroup_id Id of the user group we should bind to
289
     *
290
     * @return Boolean
291
     */
292
    public function updateUgroupBinding($ugroup_id, $source_ugroup_id = null) {
293
        $ugroup = $this->getById($ugroup_id);
294
        if ($source_ugroup_id === null) {
295
            $this->getEventManager()->processEvent(
296
                Event::UGROUP_MANAGER_UPDATE_UGROUP_BINDING_REMOVE,
297
                array(
298
                    'ugroup' => $ugroup
299
                )
300
            );
301
        } else {
302
            $source = $this->getById($source_ugroup_id);
303
            $this->getEventManager()->processEvent(
304
                Event::UGROUP_MANAGER_UPDATE_UGROUP_BINDING_ADD,
305
                array(
306
                    'ugroup' => $ugroup,
307
                    'source' => $source,
308
                )
309
            );
310
        }
311
        return $this->getDao()->updateUgroupBinding($ugroup_id, $source_ugroup_id);
312
    }
313
314
    /**
315
     * Wrapper to retrieve the source user group from a given bound ugroup id
316
     *
317
     * @param Integer $ugroupId The source ugroup id
318
     *
319
     * @return DataAccessResult
320
     */
321
    public function getUgroupBindingSource($ugroupId) {
322
        $dar = $this->getDao()->getUgroupBindingSource($ugroupId);
323
        if ($dar && !$dar->isError() && $dar->rowCount() == 1) {
324
            return new ProjectUGroup($dar->getRow());
325
        } else {
326
            return null;
327
        }
328
    }
329
330
    /**
331
     * Wrapper for UserGroupDao
332
     *
333
     * @return UserGroupDao
334
     */
335
    public function getUserGroupDao() {
336
        return new UserGroupDao();
337
    }
338
339
    /**
340
     * Return name and id of all ugroups belonging to a specific project
341
     *
342
     * @param Integer $groupId    Id of the project
343
     * @param Array   $predefined List of predefined ugroup id
344
     *
345
     * @return DataAccessResult
346
     */
347
    public function getExistingUgroups($groupId, $predefined = null) {
348
        $dar = $this->getUserGroupDao()->getExistingUgroups($groupId, $predefined);
349
        if ($dar && !$dar->isError()) {
350
            return $dar;
351
        }
352
        return array();
353
    }
354
355
    public function createEmptyUgroup($project_id, $ugroup_name, $ugroup_description) {
356
        return ugroup_create($project_id, $ugroup_name, $ugroup_description, "cx_empty");
357
    }
358
359
    public function addUserToUgroup($project_id, $ugroup_id, $user_id) {
360
        return ugroup_add_user_to_ugroup($project_id, $ugroup_id, $user_id);
361
    }
362
363
    public function syncUgroupMembers(ProjectUGroup $user_group, array $users_from_references) {
364
        $this->getDao()->startTransaction();
365
366
        $current_members   = $this->getUgroupMembers($user_group);
367
        $members_to_remove = $this->getUsersToRemove($current_members, $users_from_references);
368
        $members_to_add    = $this->getUsersToAdd($current_members, $users_from_references);
369
370
        foreach ($members_to_remove as $member_to_remove) {
371
            $this->removeUserFromUserGroup($user_group, $member_to_remove);
372
        }
373
374
        foreach ($members_to_add as $member_to_add) {
375
            $this->addUserToUserGroup($user_group, $member_to_add);
376
        }
377
378
        $this->getDao()->commit();
379
    }
380
381
    /**
382
     * @return array
383
     */
384
    private function getUgroupMembers(ProjectUGroup $user_group) {
385
        $members = array();
386
387
        foreach ($user_group->getMembersIncludingSuspended() as $member) {
388
            $members[] = $member;
389
        }
390
391
        return $members;
392
    }
393
394
    private function getUsersToRemove(array $current_members, array $users_from_references) {
395
        return array_diff($current_members, $users_from_references);
396
    }
397
398
    private function getUsersToAdd(array $current_members, array $users_from_references) {
399
        return array_diff($users_from_references, $current_members);
400
    }
401
402
    private function addUserToUserGroup(ProjectUGroup $user_group, PFUser $user) {
403
        if ($user_group->getId() == ProjectUGroup::PROJECT_MEMBERS) {
404
            return account_add_user_obj_to_group($user_group->getProjectId(), $user);
405
        }
406
407
        return $user_group->addUser($user);
408
    }
409
410
    private function removeUserFromUserGroup(ProjectUGroup $user_group, PFUser $user) {
411
        if ($user_group->getId() == ProjectUGroup::PROJECT_MEMBERS) {
412
            return account_remove_user_from_group($user_group->getProjectId(), $user->getId());
413
        }
414
415
        return $user_group->removeUser($user);
416
    }
417
}