Failed Conditions
Push — multiproject/domainswitch ( 54b9a3 )
by Simon
04:31
created

InternalPageBase::setDomainAccessManager()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
/******************************************************************************
3
 * Wikipedia Account Creation Assistance tool                                 *
4
 *                                                                            *
5
 * All code in this file is released into the public domain by the ACC        *
6
 * Development Team. Please see team.json for a list of contributors.         *
7
 ******************************************************************************/
8
9
namespace Waca\Tasks;
10
11
use Exception;
12
use PDO;
13
use Waca\DataObjects\SiteNotice;
14
use Waca\DataObjects\User;
15
use Waca\Exceptions\AccessDeniedException;
16
use Waca\Exceptions\NotIdentifiedException;
17
use Waca\Fragments\NavigationMenuAccessControl;
18
use Waca\Helpers\Interfaces\IBlacklistHelper;
19
use Waca\Helpers\Interfaces\ITypeAheadHelper;
20
use Waca\Security\DomainAccessManager;
21
use Waca\Security\SecurityManager;
22
use Waca\WebRequest;
23
24
abstract class InternalPageBase extends PageBase
25
{
26
    use NavigationMenuAccessControl;
27
28
    /** @var ITypeAheadHelper */
29
    private $typeAheadHelper;
30
    /** @var SecurityManager */
31
    private $securityManager;
32
    /** @var IBlacklistHelper */
33
    private $blacklistHelper;
34
    /** @var DomainAccessManager */
35
    private $domainAccessManager;
36
37
    /**
38
     * @return ITypeAheadHelper
39
     */
40
    public function getTypeAheadHelper()
41
    {
42
        return $this->typeAheadHelper;
43
    }
44
45
    /**
46
     * @param ITypeAheadHelper $typeAheadHelper
47
     */
48
    public function setTypeAheadHelper(ITypeAheadHelper $typeAheadHelper)
49
    {
50
        $this->typeAheadHelper = $typeAheadHelper;
51
    }
52
53
    /**
54
     * Runs the page code
55
     *
56
     * @throws Exception
57
     * @category Security-Critical
58
     */
59
    final public function execute()
60
    {
61
        if ($this->getRouteName() === null) {
0 ignored issues
show
introduced by
The condition $this->getRouteName() === null is always false.
Loading history...
62
            throw new Exception("Request is unrouted.");
63
        }
64
65
        if ($this->getSiteConfiguration() === null) {
66
            throw new Exception("Page has no configuration!");
67
        }
68
69
        $this->setupPage();
70
71
        $this->touchUserLastActive();
72
73
        $currentUser = User::getCurrent($this->getDatabase());
74
75
        // Hey, this is also a security barrier, in addition to the below. Separated out for readability.
76
        if (!$this->isProtectedPage()) {
77
            // This page is /not/ a protected page, as such we can just run it.
78
            $this->runPage();
79
80
            return;
81
        }
82
83
        // Security barrier.
84
        //
85
        // This code essentially doesn't care if the user is logged in or not, as the security manager hides all that
86
        // away for us
87
        $securityResult = $this->getSecurityManager()->allows(get_called_class(), $this->getRouteName(), $currentUser);
88
        if ($securityResult === SecurityManager::ALLOWED) {
89
            // We're allowed to run the page, so let's run it.
90
            $this->runPage();
91
        }
92
        else {
93
            $this->handleAccessDenied($securityResult);
94
95
            // Send the headers
96
            $this->sendResponseHeaders();
97
        }
98
    }
99
100
    /**
101
     * Performs final tasks needed before rendering the page.
102
     */
103
    final public function finalisePage()
104
    {
105
        parent::finalisePage();
106
107
        $database = $this->getDatabase();
108
        $currentUser = User::getCurrent($database);
109
110
        if ($this->barrierTest('viewSiteNotice', User::getCurrent($database), 'GlobalInfo')) {
111
            $siteNotice = SiteNotice::get($this->getDatabase());
112
            $siteNoticeHash = sha1($siteNotice);
113
114
            if (WebRequest::testSiteNoticeCookieValue($siteNoticeHash)) {
115
                $this->assign('siteNoticeState', 'd-none');
116
            }
117
            else {
118
                $this->assign('siteNoticeState', 'd-block');
119
            }
120
121
            $this->assign('siteNoticeText', $siteNotice);
122
            $this->assign('siteNoticeVersion', $siteNoticeHash);
123
        }
124
125
        if ($this->barrierTest('viewOnlineUsers', User::getCurrent($database), 'GlobalInfo')) {
126
            $sql = 'SELECT * FROM user WHERE lastactive > DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 MINUTE);';
127
            $statement = $database->query($sql);
128
            $activeUsers = $statement->fetchAll(PDO::FETCH_CLASS, User::class);
129
            $this->assign('onlineusers', $activeUsers);
130
        }
131
132
        $this->setupNavMenuAccess($currentUser);
133
    }
134
135
    /**
136
     * Configures whether the page respects roles or not. You probably want this to return true.
137
     *
138
     * Set to false for public pages. You probably want this to return true.
139
     *
140
     * This defaults to true unless you explicitly set it to false. Setting it to false means anybody can do anything
141
     * on this page, so you probably want this to return true.
142
     *
143
     * @return bool
144
     * @category Security-Critical
145
     */
146
    protected function isProtectedPage()
147
    {
148
        return true;
149
    }
150
151
    protected function handleAccessDenied($denyReason)
152
    {
153
        $currentUser = User::getCurrent($this->getDatabase());
154
155
        // Not allowed to access this resource.
156
        // Firstly, let's check if we're even logged in.
157
        if ($currentUser->isCommunityUser()) {
158
            // Not logged in, redirect to login page
159
            WebRequest::setPostLoginRedirect();
160
            $this->redirect("login");
161
162
            return;
163
        }
164
        else {
165
            // Decide whether this was a rights failure, or an identification failure.
166
167
            if ($denyReason === SecurityManager::ERROR_NOT_IDENTIFIED) {
168
                // Not identified
169
                throw new NotIdentifiedException($this->getSecurityManager());
170
            }
171
            elseif ($denyReason === SecurityManager::ERROR_DENIED) {
172
                // Nope, plain old access denied
173
                throw new AccessDeniedException($this->getSecurityManager());
174
            }
175
            else {
176
                throw new Exception('Unknown response from security manager.');
177
            }
178
        }
179
    }
180
181
    /**
182
     * Tests the security barrier for a specified action.
183
     *
184
     * Don't use within templates
185
     *
186
     * @param string      $action
187
     *
188
     * @param User        $user
189
     * @param null|string $pageName
190
     *
191
     * @return bool
192
     * @category Security-Critical
193
     */
194
    final public function barrierTest($action, User $user, $pageName = null)
195
    {
196
        $page = get_called_class();
197
        if ($pageName !== null) {
198
            $page = $pageName;
199
        }
200
201
        $securityResult = $this->getSecurityManager()->allows($page, $action, $user);
202
203
        return $securityResult === SecurityManager::ALLOWED;
204
    }
205
206
    /**
207
     * Updates the lastactive timestamp
208
     */
209
    private function touchUserLastActive()
210
    {
211
        if (WebRequest::getSessionUserId() !== null) {
212
            $query = 'UPDATE user SET lastactive = CURRENT_TIMESTAMP() WHERE id = :id;';
213
            $this->getDatabase()->prepare($query)->execute(array(":id" => WebRequest::getSessionUserId()));
214
        }
215
    }
216
217
    /**
218
     * @return SecurityManager
219
     */
220
    public function getSecurityManager()
221
    {
222
        return $this->securityManager;
223
    }
224
225
    /**
226
     * @param SecurityManager $securityManager
227
     */
228
    public function setSecurityManager(SecurityManager $securityManager)
229
    {
230
        $this->securityManager = $securityManager;
231
    }
232
233
    /**
234
     * @return IBlacklistHelper
235
     */
236
    public function getBlacklistHelper()
237
    {
238
        return $this->blacklistHelper;
239
    }
240
241
    /**
242
     * @param IBlacklistHelper $blacklistHelper
243
     */
244
    public function setBlacklistHelper(IBlacklistHelper $blacklistHelper)
245
    {
246
        $this->blacklistHelper = $blacklistHelper;
247
    }
248
249
    /**
250
     * @return DomainAccessManager
251
     */
252
    public function getDomainAccessManager(): DomainAccessManager
253
    {
254
        return $this->domainAccessManager;
255
    }
256
257
    /**
258
     * @param DomainAccessManager $domainAccessManager
259
     */
260
    public function setDomainAccessManager(DomainAccessManager $domainAccessManager): void
261
    {
262
        $this->domainAccessManager = $domainAccessManager;
263
    }
264
}
265