Issues (35)

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.

code/control/Users_Account_Controller.php (10 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
/**
4
 * Controller that is used to allow users to manage their accounts via
5
 * the front end of the site.
6
 * 
7
 * @package Users
8
 * @author  i-lateral <[email protected]>
9
 */
10
class Users_Account_Controller extends Controller implements PermissionProvider
11
{
12
13
    /**
14
     * URL That you can access this from
15
     *
16
     * @config
17
     */
18
    private static $url_segment = "users/account";
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
19
20
    /**
21
     * Allowed sub-URL's on this controller
22
     * 
23
     * @var    array
24
     * @config
25
     */
26
    private static $allowed_actions = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
27
        "edit",
28
        "changepassword",
29
        "EditAccountForm",
30
        "ChangePasswordForm",
31
    );
32
33
    /**
34
     * User account associated with this controller
35
     *
36
     * @var Member
37
     */
38
    protected $member;
39
40
    /**
41
     * Getter for member
42
     *
43
     * @return Member
44
     */
45
    public function getMember()
46
    {
47
        return $this->member;
48
    }
49
50
    /**
51
     * Setter for member
52
     *
53
     * @param Member $member A member to associate
54
     * 
55
     * @return self
56
     */
57
    public function setMember(Member $member)
58
    {
59
        $this->member = $member;
60
        return $this;
61
    }
62
63
    /**
64
     * Determine if current user requires verification (based on their
65
     * account and Users verification setting).
66
     *
67
     * @return boolean
68
     */
69
    public function RequireVerification()
70
    {
71
        if (!$this->member->isVerified() && Users::config()->require_verification) {
0 ignored issues
show
The if-else statement can be simplified to return !$this->member->i...->require_verification;.
Loading history...
72
            return true;
73
        } else {
74
            return false;
75
        }
76
    }
77
78
    /**
79
     * Perorm setup when this controller is initialised
80
     *
81
     * @return void
82
     */
83
    public function init()
84
    {
85
        parent::init();
86
87
        // Check we are logged in as a user who can access front end management
88
        if (!Permission::check("USERS_MANAGE_ACCOUNT")) {
89
            Security::permissionFailure();
90
        }
91
92
        // Set our member object
93
        $member = Member::currentUser();
94
95
        if ($member instanceof Member) {
96
            $this->member = $member;
97
        }
98
    }
99
100
    /**
101
     * Get the link to this controller
102
     * 
103
     * @param string $action The URL endpoint for this controller
0 ignored issues
show
Should the type for parameter $action not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
104
     * 
105
     * @return string
106
     */
107
    public function Link($action = null)
108
    {
109
        return Controller::join_links(
110
            $this->config()->url_segment,
111
            $action
112
        );
113
    }
114
115
    /**
116
     * Get an absolute link to this controller
117
     *
118
     * @param string $action The URL endpoint for this controller
0 ignored issues
show
Should the type for parameter $action not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
119
     * 
120
     * @return string
0 ignored issues
show
Should the return type not be false|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
121
     */
122
    public function AbsoluteLink($action = null)
123
    {
124
        return Director::absoluteURL($this->Link($action));
125
    }
126
127
    /**
128
     * Get a relative (to the root url of the site) link to this
129
     * controller
130
     *
131
     * @param string $action The URL endpoint for this controller 
0 ignored issues
show
Should the type for parameter $action not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
132
     * 
133
     * @return string
134
     */
135
    public function RelativeLink($action = null)
136
    {
137
        return Controller::join_links(
138
            $this->Link($action)
139
        );
140
    }
141
142
    /**
143
     * If content controller exists, return it's menu function
144
     *
145
     * @param int $level Menu level to return.
146
     * 
147
     * @return ArrayList
148
     */
149 View Code Duplication
    public function getMenu($level = 1)
0 ignored issues
show
This method seems to be duplicated in 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...
150
    {
151
        if (class_exists(ContentController::class)) {
152
            $controller = Injector::inst()->get(ContentController::class);
153
            return $controller->getMenu($level);
154
        }
155
    }
156
157
    /**
158
     * Shortcut for getMenu
159
     * 
160
     * @param int $level Menu level to return.
161
     * 
162
     * @return ArrayList
163
     */
164
    public function Menu($level)
0 ignored issues
show
The parameter $level is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
165
    {
166
        return $this->getMenu();
167
    }
168
169
    /**
170
     * Display the currently outstanding orders for the current user
171
     * 
172
     * @return HTMLText
173
     */
174
    public function index()
175
    {
176
        // Setup default profile summary sections
177
        $sections = ArrayList::create();
178
179
        $sections->push(
180
            ArrayData::create(
181
                array(
182
                "Title" => "",
183
                "Content" => $this->renderWith(
184
                    "UsersProfileSummary",
185
                    array("CurrentUser" => Member::currentUser())
186
                )
187
                )
188
            )
189
        );
190
191
        // Allow users to add extra content sections to the
192
        // summary
193
        $this->extend("updateIndexSections", $sections);
194
195
        $this->customise(
196
            array(
197
            "Title" => _t('Users.ProfileSummary', 'Profile Summary'),
198
            "MetaTitle" => _t('Users.ProfileSummary', 'Profile Summary'),
199
            "Content" => $this->renderWith(
200
                "UsersAccountSections",
201
                array("Sections" => $sections)
202
            )
203
            )
204
        );
205
206
        $this->extend("onBeforeIndex");
207
208
        return $this->renderWith(
209
            array(
210
            "UserAccount",
211
            "Page"
212
            )
213
        );
214
    }
215
216
    public function edit()
217
    {
218
        $member = Member::currentUser();
219
        $form = $this->EditAccountForm();
220
221
        if ($member instanceof Member) {
222
            $form->loadDataFrom($member);
223
        }
224
225
        $this->customise(
226
            array(
227
            "Title" => _t("Users.EditAccountDetails", "Edit account details"),
228
            "MetaTitle" => _t("Users.EditAccountDetails", "Edit account details"),
229
            "Form"  => $form
230
            )
231
        );
232
233
        $this->extend("onBeforeEdit");
234
235
        return $this->renderWith(
236
            array(
237
            "UserAccount_edit",
238
            "UserAccount",
239
            "Page"
240
            )
241
        );
242
    }
243
244
    public function changepassword()
245
    {
246
        // Set the back URL for this form
247
        $back_url = Controller::join_links(
248
            $this->Link("changepassword"),
249
            "?s=1"
250
        );
251
        
252
        Session::set("BackURL", $back_url);
253
        
254
        $form = $this->ChangePasswordForm();
255
        
256
        // Is password changed, set a session message.
257
        $password_set = $this->request->getVar("s");
258
        if($password_set && $password_set == 1) {
259
            $form->sessionMessage(
260
                _t("Users.PasswordChangedSuccessfully", "Password Changed Successfully"),
261
                "good"
262
            );
263
        }
264
265
        $this->customise(
266
            array(
267
            "Title" => _t("Security.ChangeYourPassword", "Change your password"),
268
            "MetaTitle" => _t("Security.ChangeYourPassword", "Change your password"),
269
            "Form"  => $form
270
            )
271
        );
272
273
        $this->extend("onBeforeChangePassword");
274
275
        return $this->renderWith(
276
            array(
277
            "UserAccount_changepassword",
278
            "UserAccount",
279
            "Page"
280
            )
281
        );
282
    }
283
284
    /**
285
     * Factory for generating a profile form. The form can be expanded using an
286
     * extension class and calling the updateEditProfileForm method.
287
     *
288
     * @return Form
289
     */
290
    public function EditAccountForm()
291
    {
292
        $form = Users_EditAccountForm::create($this, "EditAccountForm");
293
294
        $this->extend("updateEditAccountForm", $form);
295
296
        return $form;
297
    }
298
299
    /**
300
     * Factory for generating a change password form. The form can be expanded
301
     * using an extension class and calling the updateChangePasswordForm method.
302
     *
303
     * @return Form
304
     */
305
    public function ChangePasswordForm()
306
    {
307
        $form = ChangePasswordForm::create($this, "ChangePasswordForm");
308
309
        $form
310
            ->Actions()
311
            ->find("name", "action_doChangePassword")
312
            ->addExtraClass("btn")
313
            ->addExtraClass("btn-green");
314
315
        $cancel_btn = LiteralField::create(
316
            "CancelLink",
317
            '<a href="' . $this->Link() . '" class="btn btn-red">'. _t("Users.CANCEL", "Cancel") .'</a>'
318
        );
319
320
        $form
321
            ->Actions()
322
            ->insertBefore($cancel_btn, "action_doChangePassword");
0 ignored issues
show
'action_doChangePassword' is of type string, but the function expects a object<FormField>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
323
324
        $this->extend("updateChangePasswordForm", $form);
325
326
        return $form;
327
    }
328
329
    /**
330
     * Return a list of nav items for managing a users profile. You can add new
331
     * items to this menu using the "updateAccountMenu" extension
332
     *
333
     * @return ArrayList
334
     */
335
    public function getAccountMenu()
336
    {
337
        $menu = ArrayList::create();
338
        
339
        $curr_action = $this->request->param("Action");
340
341
        $menu->add(
342
            ArrayData::create(
343
                array(
344
                "ID"    => 0,
345
                "Title" => _t('Users.PROFILESUMMARY', "Profile Summary"),
346
                "Link"  => $this->Link(),
347
                "LinkingMode" => (!$curr_action) ? "current" : "link"
348
                )
349
            )
350
        );
351
352
        $menu->add(
353
            ArrayData::create(
354
                array(
355
                "ID"    => 10,
356
                "Title" => _t('Users.EDITDETAILS', "Edit account details"),
357
                "Link"  => $this->Link("edit"),
358
                "LinkingMode" => ($curr_action == "edit") ? "current" : "link"
359
                )
360
            )
361
        );
362
363
        $menu->add(
364
            ArrayData::create(
365
                array(
366
                "ID"    => 30,
367
                "Title" => _t('Users.CHANGEPASSWORD', "Change password"),
368
                "Link"  => $this->Link("changepassword"),
369
                "LinkingMode" => ($curr_action == "changepassword") ? "current" : "link"
370
                )
371
            )
372
        );
373
374
        $this->extend("updateAccountMenu", $menu);
375
376
        return $menu->sort("ID", "ASC");
377
    }
378
379
    public function providePermissions()
380
    {
381
        return array(
382
            "USERS_MANAGE_ACCOUNT" => array(
383
                'name' => 'Manage user account',
384
                'help' => 'Allow user to manage their account details',
385
                'category' => 'Frontend Users',
386
                'sort' => 100
387
            ),
388
            "USERS_VERIFIED" => array(
389
                'name' => 'Verified user',
390
                'help' => 'Users have verified their account',
391
                'category' => 'Frontend Users',
392
                'sort' => 100
393
            ),
394
        );
395
    }
396
}
397