Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
68.09% covered (warning)
68.09%
32 / 47
76.92% covered (warning)
76.92%
10 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiLogout
69.57% covered (warning)
69.57%
32 / 46
76.92% covered (warning)
76.92%
10 / 13
25.15
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 doGlobalLogout
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 doLocalLogout
43.75% covered (danger)
43.75%
7 / 16
0.00% covered (danger)
0.00%
0 / 1
4.60
 callUserLogoutComplete
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getAllowedParams
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 mustBePosted
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 needsToken
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isWriteMode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWebUITokenSalt
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isReadMode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getHelpUrls
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Copyright © 2008 Yuri Astrakhan "<Firstname><Lastname>@gmail.com",
4 *
5 * @license GPL-2.0-or-later
6 * @file
7 */
8
9namespace MediaWiki\Api;
10
11use MediaWiki\Session\BotPasswordSessionProvider;
12use MediaWiki\Session\SessionManager;
13use MediaWiki\User\User;
14use Wikimedia\ParamValidator\ParamValidator;
15
16/**
17 * API module to allow users to log out of the wiki. API equivalent of
18 * Special:Userlogout.
19 *
20 * @ingroup API
21 */
22class ApiLogout extends ApiBase {
23
24    public function __construct(
25        ApiMain $main,
26        string $action,
27        private readonly SessionManager $sessionManager
28    ) {
29        parent::__construct( $main, $action );
30    }
31
32    public function execute() {
33        if ( $this->getUser()->isAnon() ) {
34            // Cannot log out an anon user, so add a warning and return early.
35            $this->addWarning( 'apierror-mustbeloggedin-generic', 'notloggedin' );
36            return;
37        }
38
39        if ( $this->getParameter( 'global' ) ) {
40            $this->checkUserRightsAny( 'logout' );
41            $this->doGlobalLogout();
42        } else {
43            $this->doLocalLogout();
44        }
45    }
46
47    protected function doGlobalLogout(): void {
48        $user = $this->getUser();
49        // remove cookies
50        $this->getRequest()->getSession()->unpersist();
51        $this->sessionManager->invalidateSessionsForUser( $user );
52        $this->callUserLogoutComplete( $user, $user->getName() );
53    }
54
55    protected function doLocalLogout(): void {
56        $user = $this->getUser();
57        $oldUserName = $user->getName();
58        $session = $this->getRequest()->getSession();
59
60        // Handle bot password logout specially
61        if ( $session->getProvider() instanceof BotPasswordSessionProvider ) {
62            $session->unpersist();
63            return;
64        }
65
66        // Make sure it's possible to log out
67        if ( !$session->canSetUser() ) {
68            $this->dieWithError(
69                [
70                    'cannotlogoutnow-text',
71                    $session->getProvider()->describe( $this->getErrorFormatter()->getLanguage() )
72                ],
73                'cannotlogout'
74            );
75        }
76
77        $user->logout();
78        $this->callUserLogoutComplete( $user, $oldUserName );
79    }
80
81    protected function callUserLogoutComplete( User $user, string $oldUserName ) {
82        // Give extensions to do something after user logout
83        $injected_html = '';
84        $this->getHookRunner()->onUserLogoutComplete( $user, $injected_html, $oldUserName );
85    }
86
87    /** @inheritDoc */
88    protected function getAllowedParams() {
89        return [
90            'global' => [
91                ParamValidator::PARAM_TYPE => 'boolean',
92                ParamValidator::PARAM_DEFAULT => false,
93            ],
94        ];
95    }
96
97    /** @inheritDoc */
98    public function mustBePosted() {
99        return true;
100    }
101
102    /** @inheritDoc */
103    public function needsToken() {
104        return 'csrf';
105    }
106
107    /** @inheritDoc */
108    public function isWriteMode() {
109        // While core is optimized by default to not require DB writes on log out,
110        // these are authenticated POST requests and extensions (eg. CheckUser) are
111        // allowed to perform DB writes here without warnings.
112        return true;
113    }
114
115    /** @inheritDoc */
116    protected function getWebUITokenSalt( array $params ) {
117        return 'logoutToken';
118    }
119
120    /** @inheritDoc */
121    public function isReadMode() {
122        return false;
123    }
124
125    /** @inheritDoc */
126    protected function getExamplesMessages() {
127        return [
128            'action=logout&token=123ABC'
129                => 'apihelp-logout-example-logout',
130        ];
131    }
132
133    /** @inheritDoc */
134    public function getHelpUrls() {
135        return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Logout';
136    }
137}
138
139/** @deprecated class alias since 1.43 */
140class_alias( ApiLogout::class, 'ApiLogout' );