Completed
Push — authenticator-refactor ( 7dc887...371abb )
by Simon
06:49
created

CMSSecurity::redirectToExternalLogin()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 18
nc 1
nop 0
dl 0
loc 27
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Security;
4
5
use SilverStripe\Admin\AdminRootController;
6
use SilverStripe\Control\HTTPResponse;
7
use SilverStripe\Control\Session;
8
use SilverStripe\Core\Convert;
9
use SilverStripe\Control\Director;
10
use SilverStripe\Control\Controller;
11
use SilverStripe\Core\Injector\Injector;
12
use SilverStripe\ORM\FieldType\DBField;
13
use SilverStripe\Security\MemberAuthenticator\CMSMemberAuthenticator;
14
use SilverStripe\View\Requirements;
15
16
/**
17
 * Provides a security interface functionality within the cms
18
 */
19
class CMSSecurity extends Security
20
{
21
22
    private static $casting = 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...
23
        'Title' => 'HTMLFragment'
24
    );
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
        'login',
28
        'LoginForm',
29
        'success'
30
    );
31
32
    /**
33
     * Enable in-cms reauthentication
34
     *
35
     * @var boolean
36
     * @config
37
     */
38
    private static $reauth_enabled = true;
39
40
    /**
41
     * @var string Default CMS Authenticator
42
     */
43
    protected static $default_authenticator = 'cms';
44
45
    protected function init()
46
    {
47
        parent::init();
48
49
        Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/vendor.js');
50
    }
51
52
    public function login($request = null, $service = Authenticator::CMS_LOGIN)
53
    {
54
        return parent::login($request, Authenticator::CMS_LOGIN);
55
    }
56
57
    public function Link($action = null)
58
    {
59
        /** @skipUpgrade */
60
        return Controller::join_links(Director::baseURL(), "CMSSecurity", $action);
61
    }
62
63
    protected function getAuthenticator($name = 'cms')
64
    {
65
        return parent::getAuthenticator($name);
66
    }
67
68
    public function getApplicableAuthenticators($service = Authenticator::CMS_LOGIN)
69
    {
70
        return parent::getApplicableAuthenticators($service);
71
    }
72
73
    /**
74
     * Get known logged out member
75
     *
76
     * @return Member
77
     */
78
    public function getTargetMember()
79
    {
80
        if ($tempid = $this->getRequest()->requestVar('tempid')) {
81
            return Member::member_from_tempid($tempid);
82
        }
83
84
        return null;
85
    }
86
87
    public function getResponseController($title)
88
    {
89
        // Use $this to prevent use of Page to render underlying templates
90
        return $this;
91
    }
92
93
    protected function getLoginMessage(&$messageType = null)
94
    {
95
        return parent::getLoginMessage($messageType)
96
            ?: _t(
97
                'SilverStripe\\Security\\CMSSecurity.LoginMessage',
98
                '<p>If you have any unsaved work you can return to where you left off by logging back in below.</p>'
99
            );
100
    }
101
102
    public function getTitle()
103
    {
104
        // Check if logged in already
105
        if (Security::getCurrentUser()) {
106
            return _t('SilverStripe\\Security\\CMSSecurity.SUCCESS', 'Success');
107
        }
108
109
        // Display logged-out message
110
        $member = $this->getTargetMember();
111
        if ($member) {
112
            return _t(
113
                'SilverStripe\\Security\\CMSSecurity.TimedOutTitleMember',
114
                'Hey {name}!<br />Your session has timed out.',
115
                'Title for CMS popup login form for a known user',
116
                array('name' => $member->FirstName)
117
            );
118
        } else {
119
            return _t(
120
                'SilverStripe\\Security\\CMSSecurity.TimedOutTitleAnonymous',
121
                'Your session has timed out.',
122
                'Title for CMS popup login form without a known user'
123
            );
124
        }
125
    }
126
127
    /**
128
     * Redirects the user to the external login page
129
     *
130
     * @return HTTPResponse
131
     */
132
    protected function redirectToExternalLogin()
133
    {
134
        $loginURL = Security::create()->Link('login');
135
        $loginURLATT = Convert::raw2att($loginURL);
136
        $loginURLJS = Convert::raw2js($loginURL);
137
        $message = _t(
138
            'SilverStripe\\Security\\CMSSecurity.INVALIDUSER',
139
            '<p>Invalid user. <a target="_top" href="{link}">Please re-authenticate here</a> to continue.</p>',
140
            'Message displayed to user if their session cannot be restored',
141
            array('link' => $loginURLATT)
142
        );
143
        $response = $this->getResponse();
144
        $response->setStatusCode(200);
145
        $response->setBody(<<<PHP
146
<!DOCTYPE html>
147
<html><body>
148
$message
149
<script type="application/javascript">
150
setTimeout(function(){top.location.href = "$loginURLJS";}, 0);
151
</script>
152
</body></html>
153
PHP
154
        );
155
        $this->setResponse($response);
156
157
        return $response;
158
    }
159
160
    protected function preLogin()
161
    {
162
        // If no member has been previously logged in for this session, force a redirect to the main login page
163
        if (!$this->getTargetMember()) {
164
            return $this->redirectToExternalLogin();
165
        }
166
167
        return parent::preLogin();
168
    }
169
170
    /**
171
     * Determine if CMSSecurity is enabled
172
     *
173
     * @return bool
174
     */
175
    public static function enabled()
176
    {
177
        // Disable shortcut
178
        if (!static::config()->get('reauth_enabled')) {
179
            return false;
180
        }
181
182
        return count(Security::singleton()->getApplicableAuthenticators(Authenticator::CMS_LOGIN)) > 0;
183
    }
184
185
    /**
186
     * Given a successful login, tell the parent frame to close the dialog
187
     *
188
     * @return HTTPResponse|DBField
189
     */
190
    public function success()
191
    {
192
        // Ensure member is properly logged in
193
        if (!Security::getCurrentUser() || !class_exists(AdminRootController::class)) {
194
            return $this->redirectToExternalLogin();
195
        }
196
197
        // Get redirect url
198
        $controller = $this->getResponseController(_t('SilverStripe\\Security\\CMSSecurity.SUCCESS', 'Success'));
199
        $backURLs = array(
200
            $this->getRequest()->requestVar('BackURL'),
201
            Session::get('BackURL'),
202
            Director::absoluteURL(AdminRootController::config()->url_base, true),
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string.

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...
203
        );
204
        $backURL = null;
205
        foreach ($backURLs as $backURL) {
206
            if ($backURL && Director::is_site_url($backURL)) {
207
                break;
208
            }
209
        }
210
211
        // Show login
212
        $controller = $controller->customise(array(
213
            'Content' => _t(
214
                'SilverStripe\\Security\\CMSSecurity.SUCCESSCONTENT',
215
                '<p>Login success. If you are not automatically redirected ' .
216
                '<a target="_top" href="{link}">click here</a></p>',
217
                'Login message displayed in the cms popup once a user has re-authenticated themselves',
218
                array('link' => Convert::raw2att($backURL))
219
            )
220
        ));
221
222
        return $controller->renderWith($this->getTemplatesFor('success'));
223
    }
224
}
225