Completed
Push — master ( 1be2e7...d38097 )
by Sam
23s
created

CMSSecurity::Link()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 9.4285
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\Core\Convert;
8
use SilverStripe\Control\Director;
9
use SilverStripe\Control\Controller;
10
use SilverStripe\Control\Session;
11
use SilverStripe\ORM\FieldType\DBField;
12
use SilverStripe\View\Requirements;
13
14
/**
15
 * Provides a security interface functionality within the cms
16
 */
17
class CMSSecurity extends Security
18
{
19
20
    private static $casting = array(
21
        'Title' => 'HTMLFragment'
22
    );
23
24
    private static $allowed_actions = array(
25
        'LoginForm',
26
        'success'
27
    );
28
29
    /**
30
     * Enable in-cms reauthentication
31
     *
32
     * @var boolean
33
     * @config
34
     */
35
    private static $reauth_enabled = true;
36
37
    protected function init()
38
    {
39
        parent::init();
40
41
        Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/vendor.js');
42
        Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/CMSSecurity.js');
43
    }
44
45
    public function Link($action = null)
46
    {
47
        /** @skipUpgrade */
48
        return Controller::join_links(Director::baseURL(), "CMSSecurity", $action);
49
    }
50
51
    /**
52
     * Get known logged out member
53
     *
54
     * @return Member
55
     */
56
    public function getTargetMember()
57
    {
58
        if ($tempid = $this->getRequest()->requestVar('tempid')) {
59
            return Member::member_from_tempid($tempid);
60
        }
61
        return null;
62
    }
63
64
    public function getResponseController($title)
65
    {
66
        // Use $this to prevent use of Page to render underlying templates
67
        return $this;
68
    }
69
70
    protected function getLoginMessage(&$messageType = null)
71
    {
72
        return parent::getLoginMessage($messageType)
73
            ?: _t(
74
                'CMSSecurity.LoginMessage',
75
                '<p>If you have any unsaved work you can return to where you left off by logging back in below.</p>'
76
            );
77
    }
78
79
    public function getTitle()
80
    {
81
        // Check if logged in already
82
        if (Member::currentUserID()) {
83
            return _t('CMSSecurity.SUCCESS', 'Success');
84
        }
85
86
        // Display logged-out message
87
        $member = $this->getTargetMember();
88
        if ($member) {
89
            return _t(
90
                'CMSSecurity.TimedOutTitleMember',
91
                'Hey {name}!<br />Your session has timed out.',
92
                'Title for CMS popup login form for a known user',
93
                array('name' => $member->FirstName)
94
            );
95
        } else {
96
            return _t(
97
                'CMSSecurity.TimedOutTitleAnonymous',
98
                'Your session has timed out.',
99
                'Title for CMS popup login form without a known user'
100
            );
101
        }
102
    }
103
104
    /**
105
     * Redirects the user to the external login page
106
     *
107
     * @return HTTPResponse
108
     */
109
    protected function redirectToExternalLogin()
110
    {
111
        $loginURL = Security::create()->Link('login');
112
        $loginURLATT = Convert::raw2att($loginURL);
113
        $loginURLJS = Convert::raw2js($loginURL);
114
        $message = _t(
115
            'CMSSecurity.INVALIDUSER',
116
            '<p>Invalid user. <a target="_top" href="{link}">Please re-authenticate here</a> to continue.</p>',
117
            'Message displayed to user if their session cannot be restored',
118
            array('link' => $loginURLATT)
119
        );
120
        $response = $this->getResponse();
121
        $response->setStatusCode(200);
122
        $response->setBody(<<<PHP
123
<!DOCTYPE html>
124
<html><body>
125
$message
126
<script type="application/javascript">
127
setTimeout(function(){top.location.href = "$loginURLJS";}, 0);
128
</script>
129
</body></html>
130
PHP
131
        );
132
        $this->setResponse($response);
133
        return $response;
134
    }
135
136
    protected function preLogin()
137
    {
138
        // If no member has been previously logged in for this session, force a redirect to the main login page
139
        if (!$this->getTargetMember()) {
140
            return $this->redirectToExternalLogin();
141
        }
142
143
        return parent::preLogin();
144
    }
145
146
    public function GetLoginForms()
147
    {
148
        $forms = array();
149
        $authenticators = Authenticator::get_authenticators();
150
        foreach ($authenticators as $authenticator) {
151
            // Get only CMS-supporting authenticators
152
            if ($authenticator::supports_cms()) {
153
                $forms[] = $authenticator::get_cms_login_form($this);
154
            }
155
        }
156
        return $forms;
157
    }
158
159
    /**
160
     * Determine if CMSSecurity is enabled
161
     *
162
     * @return bool
163
     */
164
    public static function enabled()
165
    {
166
        // Disable shortcut
167
        if (!static::config()->reauth_enabled) {
168
            return false;
169
        }
170
171
        // Count all cms-supported methods
172
        $authenticators = Authenticator::get_authenticators();
173
        foreach ($authenticators as $authenticator) {
174
            // Supported if at least one authenticator is supported
175
            if ($authenticator::supports_cms()) {
176
                return true;
177
            }
178
        }
179
        return false;
180
    }
181
182
    public function LoginForm()
183
    {
184
        $authenticator = $this->getAuthenticator();
185
        if ($authenticator && $authenticator::supports_cms()) {
186
            return $authenticator::get_cms_login_form($this);
187
        }
188
        user_error('Passed invalid authentication method', E_USER_ERROR);
189
    }
190
191
    /**
192
     * Given a successful login, tell the parent frame to close the dialog
193
     *
194
     * @return HTTPResponse|DBField
195
     */
196
    public function success()
197
    {
198
        // Ensure member is properly logged in
199
        if (!Member::currentUserID()) {
200
            return $this->redirectToExternalLogin();
201
        }
202
203
        // Get redirect url
204
        $controller = $this->getResponseController(_t('CMSSecurity.SUCCESS', 'Success'));
205
        $backURLs = array(
206
            $this->getRequest()->requestVar('BackURL'),
207
            Session::get('BackURL'),
208
            Director::absoluteURL(AdminRootController::config()->url_base, true),
209
        );
210
        $backURL = null;
211
        foreach ($backURLs as $backURL) {
212
            if ($backURL && Director::is_site_url($backURL)) {
213
                break;
214
            }
215
        }
216
217
        // Show login
218
        $controller = $controller->customise(array(
219
            'Content' => _t(
220
                'CMSSecurity.SUCCESSCONTENT',
221
                '<p>Login success. If you are not automatically redirected '.
222
                '<a target="_top" href="{link}">click here</a></p>',
223
                'Login message displayed in the cms popup once a user has re-authenticated themselves',
224
                array('link' => $backURL)
225
            )
226
        ));
227
228
        return $controller->renderWith($this->getTemplatesFor('success'));
229
    }
230
}
231