Merge "Update searchdisabled message with docs and better link target"
[mediawiki.git] / includes / Permissions / GrantsInfo.php
blob6ae85c01d6d491f2723b5b16a66357cdeac27b12
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.
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.
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
18 * @file
21 namespace MediaWiki\Permissions;
23 use MediaWiki\Config\ServiceOptions;
24 use MediaWiki\MainConfigNames;
26 /**
27 * Users can authorize applications to use their account via OAuth. Grants are used to
28 * limit permissions for these application. This service allows application logic to
29 * access grants.
31 * @since 1.38
33 class GrantsInfo {
34 /**
35 * Risk level classification for grants which aren't particularly risky. These grants might
36 * be abused, e.g. for vandalism, but the effect is easy to undo and the efficiency of abusing
37 * them isn't particularly different from registering new user accounts and using those for
38 * abuse.
39 * Note that risk levels depend on the use case; the default classification is meant for
40 * "normal" (public, open registration) wikis. Classification for e.g. a private wiki holding
41 * confidential information could be quite different.
43 public const RISK_LOW = 'low';
45 /**
46 * Risk level classification for grants which can be used for disruptive vandalism or other
47 * kinds of abuse that couldn't be achieved just by registering new accounts, such as main
48 * page vandalism, vandalism of popular templates, page merge vandalism, or blocks.
50 public const RISK_VANDALISM = 'vandalism';
52 /**
53 * Risk level classification for grants which can be used to cause damage that is hard or
54 * impossible to undo, such as exfiltrating sensitive private data or creating security
55 * vulnerabilities.
57 public const RISK_SECURITY = 'security';
59 /**
60 * Risk level classification for grants which are used for internal purposes and should not
61 * be handed out.
63 public const RISK_INTERNAL = 'internal';
65 /**
66 * @internal For use by ServiceWiring
68 public const CONSTRUCTOR_OPTIONS = [
69 MainConfigNames::GrantPermissions,
70 MainConfigNames::GrantPermissionGroups,
71 MainConfigNames::GrantRiskGroups,
74 private ServiceOptions $options;
76 public function __construct(
77 ServiceOptions $options
78 ) {
79 $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
80 $this->options = $options;
83 /**
84 * List all known grants.
85 * @return string[]
87 public function getValidGrants(): array {
88 return array_keys( $this->options->get( MainConfigNames::GrantPermissions ) );
91 /**
92 * Map all grants to corresponding user rights.
93 * @return string[][] grant => array of rights in the grant
95 public function getRightsByGrant(): array {
96 $res = [];
97 foreach ( $this->options->get( MainConfigNames::GrantPermissions ) as $grant => $rights ) {
98 $res[$grant] = array_keys( array_filter( $rights ) );
100 return $res;
104 * Fetch the rights allowed by a set of grants.
105 * @param string[]|string $grants
106 * @return string[]
108 public function getGrantRights( $grants ): array {
109 $rights = [];
110 foreach ( (array)$grants as $grant ) {
111 if ( isset( $this->options->get( MainConfigNames::GrantPermissions )[$grant] ) ) {
112 $rights = array_merge(
113 $rights,
114 array_keys( array_filter( $this->options->get( MainConfigNames::GrantPermissions )[$grant] ) )
118 return array_unique( $rights );
122 * Test that all grants in the list are known.
123 * @param string[] $grants
124 * @return bool
126 public function grantsAreValid( array $grants ): bool {
127 return array_diff( $grants, $this->getValidGrants() ) === [];
131 * Divide the grants into groups.
132 * @param string[]|null $grantsFilter
133 * @return string[][] Map of (group => (grant list))
135 public function getGrantGroups( ?array $grantsFilter = null ): array {
136 if ( is_array( $grantsFilter ) ) {
137 $grantsFilter = array_fill_keys( $grantsFilter, true );
140 $groups = [];
141 foreach ( $this->options->get( MainConfigNames::GrantPermissions ) as $grant => $rights ) {
142 if ( $grantsFilter !== null && !isset( $grantsFilter[$grant] ) ) {
143 continue;
145 if ( isset( $this->options->get( MainConfigNames::GrantPermissionGroups )[$grant] ) ) {
146 $groups[$this->options->get( MainConfigNames::GrantPermissionGroups )[$grant]][] = $grant;
147 } else {
148 $groups['other'][] = $grant;
152 return $groups;
156 * Get the list of grants that are hidden and should always be granted.
157 * @return string[]
159 public function getHiddenGrants(): array {
160 $grants = [];
161 foreach ( $this->options->get( MainConfigNames::GrantPermissionGroups ) as $grant => $group ) {
162 if ( $group === 'hidden' ) {
163 $grants[] = $grant;
166 return $grants;
170 * Returns a map of grant name => risk group. The risk groups are the GrantsInfo::RISK_*
171 * constants, plus $default for grants where the risk level is not defined.
172 * @param string $default Default risk group to assign to grants for which no risk group
173 * is configured. $default does not have to be one of the RISK_* constants.
174 * @return string[]
175 * @since 1.42
177 public function getRiskGroupsByGrant( string $default = 'unknown' ): array {
178 $res = [];
179 $grantRiskGroups = $this->options->get( MainConfigNames::GrantRiskGroups );
180 foreach ( $this->options->get( MainConfigNames::GrantPermissions ) as $grant => $_ ) {
181 $res[$grant] = $grantRiskGroups[$grant] ?? $default;
183 return $res;