1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 */
18
19namespace MediaWiki\Extension\OATHAuth\Api\Module;
20
21use ApiQuery;
22use ApiQueryBase;
23use ApiResult;
24use ManualLogEntry;
25use MediaWiki\MediaWikiServices;
26use User;
27use Wikimedia\ParamValidator\ParamValidator;
28
29/**
30 * Query module to check if a user has OATH authentication enabled.
31 *
32 * Usage requires the 'oathauth-api-all' grant which is not given to any group
33 * by default. Use of this API is security sensitive and should not be granted
34 * lightly. Configuring a special 'oathauth' user group is recommended.
35 *
36 * @ingroup API
37 * @ingroup Extensions
38 */
39class ApiQueryOATH extends ApiQueryBase {
40	/**
41	 * @param ApiQuery $query
42	 * @param string $moduleName
43	 */
44	public function __construct( $query, $moduleName ) {
45		parent::__construct( $query, $moduleName, 'oath' );
46	}
47
48	public function execute() {
49		$params = $this->extractRequestParams();
50		if ( $params['user'] === null ) {
51			$params['user'] = $this->getUser()->getName();
52		}
53
54		$this->checkUserRightsAny( [ 'oathauth-api-all', 'oathauth-verify-user' ] );
55
56		$hasOAthauthApiAll = $this->getPermissionManager()
57			->userHasRight(
58				$this->getUser(),
59				'oathauth-api-all'
60			);
61
62		$reasonProvided = $params['reason'] !== null && $params['reason'] !== '';
63		if ( !$hasOAthauthApiAll && !$reasonProvided ) {
64			$this->dieWithError( [ 'apierror-missingparam', 'reason' ] );
65		}
66
67		$user = User::newFromName( $params['user'] );
68		if ( $user === false ) {
69			$this->dieWithError( 'noname' );
70		}
71
72		$result = $this->getResult();
73		$data = [
74			ApiResult::META_BC_BOOLS => [ 'enabled' ],
75			'enabled' => false,
76		];
77
78		if ( !$user->isAnon() ) {
79			$userRepo = MediaWikiServices::getInstance()->getService( 'OATHUserRepository' );
80			$authUser = $userRepo->findByUser( $user );
81			$data['enabled'] = $authUser &&
82				$authUser->getModule() !== null &&
83				$authUser->getModule()->isEnabled( $authUser );
84
85			// Log if the user doesn't have oathauth-api-all or if a reason is provided
86			if ( !$hasOAthauthApiAll || $reasonProvided ) {
87				$logEntry = new ManualLogEntry( 'oath', 'verify' );
88				$logEntry->setPerformer( $this->getUser() );
89				$logEntry->setTarget( $user->getUserPage() );
90				$logEntry->setComment( $params['reason'] );
91				$logEntry->insert();
92			}
93		}
94		$result->addValue( 'query', $this->getModuleName(), $data );
95	}
96
97	/**
98	 * @param array $params
99	 *
100	 * @return string
101	 */
102	public function getCacheMode( $params ) {
103		return 'private';
104	}
105
106	public function isInternal() {
107		return true;
108	}
109
110	/**
111	 * @return array
112	 */
113	public function getAllowedParams() {
114		return [
115			'user' => [
116				ParamValidator::PARAM_TYPE => 'user',
117			],
118			'reason' => [
119				ParamValidator::PARAM_TYPE => 'string',
120			],
121		];
122	}
123
124	/**
125	 * @return array
126	 */
127	protected function getExamplesMessages() {
128		return [
129			'action=query&meta=oath'
130				=> 'apihelp-query+oath-example-1',
131			'action=query&meta=oath&oathuser=Example'
132				=> 'apihelp-query+oath-example-2',
133		];
134	}
135}
136