Completed
Push — authenticator-refactor ( 4aec3f...04850c )
by Simon
06:12
created

CMSSecurity::getAuthenticator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
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\CMSAuthenticator;
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
    protected function init()
41
    {
42
        parent::init();
43
44
        Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/vendor.js');
45
    }
46
47
    public function login($request, $service = Authenticator::CMS_LOGIN)
48
    {
49
        return parent::login($request, Authenticator::CMS_LOGIN); // TODO: Change the autogenerated stub
50
    }
51
52
    public function Link($action = null)
53
    {
54
        /** @skipUpgrade */
55
        return Controller::join_links(Director::baseURL(), "CMSSecurity", $action);
56
    }
57
58
    protected function getAuthenticator($name = 'cms')
59
    {
60
        return parent::getAuthenticator($name);
61
    }
62
63
    public static function getAuthenticators($service = Authenticator::CMS_LOGIN)
64
    {
65
        return parent::getAuthenticators($service);
66
    }
67
68
    /**
69
     * Get known logged out member
70
     *
71
     * @return Member
72
     */
73
    public function getTargetMember()
74
    {
75
        if ($tempid = $this->getRequest()->requestVar('tempid')) {
76
            return Member::member_from_tempid($tempid);
77
        }
78
79
        return null;
80
    }
81
82
    public function getResponseController($title)
83
    {
84
        // Use $this to prevent use of Page to render underlying templates
85
        return $this;
86
    }
87
88
    protected function getLoginMessage(&$messageType = null)
89
    {
90
        return parent::getLoginMessage($messageType)
91
            ?: _t(
92
                'SilverStripe\\Security\\CMSSecurity.LoginMessage',
93
                '<p>If you have any unsaved work you can return to where you left off by logging back in below.</p>'
94
            );
95
    }
96
97
    public function getTitle()
98
    {
99
        // Check if logged in already
100
        if (Member::currentUserID()) {
101
            return _t('SilverStripe\\Security\\CMSSecurity.SUCCESS', 'Success');
102
        }
103
104
        // Display logged-out message
105
        $member = $this->getTargetMember();
106
        if ($member) {
107
            return _t(
108
                'SilverStripe\\Security\\CMSSecurity.TimedOutTitleMember',
109
                'Hey {name}!<br />Your session has timed out.',
110
                'Title for CMS popup login form for a known user',
111
                array('name' => $member->FirstName)
112
            );
113
        } else {
114
            return _t(
115
                'SilverStripe\\Security\\CMSSecurity.TimedOutTitleAnonymous',
116
                'Your session has timed out.',
117
                'Title for CMS popup login form without a known user'
118
            );
119
        }
120
    }
121
122
    /**
123
     * Redirects the user to the external login page
124
     *
125
     * @return HTTPResponse
126
     */
127
    protected function redirectToExternalLogin()
128
    {
129
        $loginURL = Security::create()->Link('login');
130
        $loginURLATT = Convert::raw2att($loginURL);
131
        $loginURLJS = Convert::raw2js($loginURL);
132
        $message = _t(
133
            'SilverStripe\\Security\\CMSSecurity.INVALIDUSER',
134
            '<p>Invalid user. <a target="_top" href="{link}">Please re-authenticate here</a> to continue.</p>',
135
            'Message displayed to user if their session cannot be restored',
136
            array('link' => $loginURLATT)
137
        );
138
        $response = $this->getResponse();
139
        $response->setStatusCode(200);
140
        $response->setBody(<<<PHP
141
<!DOCTYPE html>
142
<html><body>
143
$message
144
<script type="application/javascript">
145
setTimeout(function(){top.location.href = "$loginURLJS";}, 0);
146
</script>
147
</body></html>
148
PHP
149
        );
150
        $this->setResponse($response);
151
152
        return $response;
153
    }
154
155
    protected function preLogin()
156
    {
157
        // If no member has been previously logged in for this session, force a redirect to the main login page
158
        if (!$this->getTargetMember()) {
159
            return $this->redirectToExternalLogin();
160
        }
161
162
        return parent::preLogin();
163
    }
164
165
    /**
166
     * Determine if CMSSecurity is enabled
167
     *
168
     * @return bool
169
     */
170
    public static function enabled()
171
    {
172
        // Disable shortcut
173
        if (!static::config()->get('reauth_enabled')) {
174
            return false;
175
        }
176
177
        /** @var [] $authenticators */
0 ignored issues
show
Documentation introduced by
The doc-type [] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
178
        $authenticators = Security::config()->get('authenticators');
179
        foreach ($authenticators as $name => $authenticator) {
180
            // Supported if at least one authenticator is supported
181
            $authenticator = Injector::inst()->get($authenticator);
182
            if (($authenticator->supportedServices() & Authenticator::CMS_LOGIN)
183
                && Security::hasAuthenticator($name)
184
            ) {
185
                return true;
186
            }
187
        }
188
189
        return false;
190
    }
191
192
    /**
193
     * Given a successful login, tell the parent frame to close the dialog
194
     *
195
     * @return HTTPResponse|DBField
196
     */
197
    public function success()
198
    {
199
        // Ensure member is properly logged in
200
        if (!Member::currentUserID() || !class_exists(AdminRootController::class)) {
201
            return $this->redirectToExternalLogin();
202
        }
203
204
        // Get redirect url
205
        $controller = $this->getResponseController(_t('SilverStripe\\Security\\CMSSecurity.SUCCESS', 'Success'));
206
        $backURLs = array(
207
            $this->getRequest()->requestVar('BackURL'),
208
            Session::get('BackURL'),
209
            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...
210
        );
211
        $backURL = null;
212
        foreach ($backURLs as $backURL) {
213
            if ($backURL && Director::is_site_url($backURL)) {
214
                break;
215
            }
216
        }
217
218
        // Show login
219
        $controller = $controller->customise(array(
220
            'Content' => _t(
221
                'SilverStripe\\Security\\CMSSecurity.SUCCESSCONTENT',
222
                '<p>Login success. If you are not automatically redirected ' .
223
                '<a target="_top" href="{link}">click here</a></p>',
224
                'Login message displayed in the cms popup once a user has re-authenticated themselves',
225
                array('link' => Convert::raw2att($backURL))
226
            )
227
        ));
228
229
        return $controller->renderWith($this->getTemplatesFor('success'));
230
    }
231
}
232