1 Whitelist MediaWiki Namespaces with $wgWhitelistRead
2 ====================================================
3 :author: Aaron Ball
4 :email: nullspoon@iohq.net
5
6
7 == {doctitle}
8
9 MediaWiki is designed for the most part to be an open document repository. In
10 most setups (presumably), everyone can read and only registered users can edit.
11 However, permissions can't get much more granular than this. For my project at
12 least, I would like to not just limit anonymous users from editing, I would
13 like to selectively limit them from reading certain things.
14
15 I looked around for quite some time until I came upon a variable you can set in
16 your LocalSettings.php file: **$wgWhitelistRead**. Basically, this variable
17 whitelists the pages specified in the array. The downside to this is you can't
18 use wildcards or namespaces/categories. You must specify a single page per
19 array value. This doesn't quite cut it for my needs. That being said, here's my
20 solution (albeit rough).
21
22 The end goal here looks like this...
23
24 * All users are blocked from reading and writing all pages
25 * Users in all groups are then given read access to the whitelisted namespaces
26 * Finally, users in the specified groups have read and write access to all
27 pages (save for the administration/sysop pages of course).
28
29
30 [[limiting-all-access]]
31 == Limiting All Access
32
33 To do this, in your LocalSettings.php file, place the following four lines...
34
35 ----
36 $wgGroupPermissions['*']['read'] = false;
37 $wgGroupPermissions['*']['edit'] = false;
38 $wgGroupPermissions['user']['read'] = false;
39 $wgGroupPermissions['user']['edit'] = false;
40 ----
41
42
43 [[granting-sysop-access]]
44 == Granting Sysop Access
45
46 Once you have the lines in the last section in your config file, your entire
47 wiki should be unavailable, even to sysop people (they are users after all). To
48 give access back to your sysop folk, place the following two lines in your
49 LocalSettings.php file
50
51 ----
52 $wgGroupPermissions['sysop']['read'] = true;
53 $wgGroupPermissions['sysop']['edit'] = true;
54 ----
55
56 This will only grant access to your sysop authenticated users. If they're not
57 already authenticated, they still can't get to the Special:UserLogin form
58 (we'll get to that in just a few) to login. They may be sysops at heart, but
59 hearts don't authenticate people without usernames and passwords.
60
61
62 [[granting-individual-group-access]]
63 == Granting Individual Group Access
64
65 Now that our sysops have permissions, next we need a custom group so we can
66 grant permissions to them. We'll call that group 'GreenTea' (yes, I'm drinking
67 some green tea right now). To do that, let's throw another few lines in the
68 LocalSettings.php file...
69
70 ----
71 $wgGroupPermissions['greentea'] =
72 $wgGroupPermissions['user']; $wgGroupPermissions['greentea']['read'] =
73 true; $wgGroupPermissions['greentea']['edit'] = true;
74 ----
75
76
77 [[granting-minimal-global-permissions]]
78 == Granting Minimal Global Permissions
79
80 Now that our group is set up, we need to whitelist the necessary and wanted
81 pages for anonymous folk to log in and/or do their thing depending on what
82 groups they are in. To do this, let's add yet another few lines to our
83 LocalSettings.php file
84
85 ----
86 $wgWhitelistRead = array(
87 'Main Page',
88 'Special:Userlogin',
89 'Special:UserLogout',
90 );
91 ----
92
93 What we just did was whitelist the main page, the login page, and the logout
94 page. This allows users to get in and out of your wiki, whether or not their
95 permissions allow them access to anything. At this point, you can log in with
96 your sysop user and put people into our previously created 'greentea' group.
97 Once that's done, the greentea users should have full access to the entire
98 wiki.
99
100 I would like to note here that that this point, users outside of the greentea
101 group will have the same permissions as anonymous/unauthenticated users. They
102 cannot read or edit any pages other than the ones currently whitelisted.
103
104
105 [[editing-mediawiki-to-whitelist-namespaces]]
106 == Editing MediaWiki to Whitelist Namespaces
107
108 This is the only part that's out of the ordinary here. We are going to edit
109 actual MediaWiki code. The big downside to doing this is that if the MediaWiki
110 instance is upgrade, it is highly likely that the changes made in this section
111 will be overwritten. Thankfully though, the changes are very simple, so making
112 them again shouldn't be a problem. They're so simple in fact, I think the
113 MediaWiki folks might actually accept my code into their branch.
114
115 To set up our MediaWiki instance so it handles regex whitelist statements, we
116 need to edit the Title.php file in the includes directory.
117
118 Firstly, we need to comment out the code that processes the whitelist variable.
119 Head to around line 1870 in Title.php and comment out just the following lines
120
121 ----
122 //Check with and without underscores
123 if ( in_array( $name, $wgWhitelistRead, true ) || in_array( $dbName, $wgWhitelistRead, true ) )
124 return true;
125 ----
126
127
128 Now that those have been commented out, we need to add in the code that will
129 process regex statements in the whitelist array. Below the lines you just
130 commented out, add the following code...
131
132 ----
133 foreach ( $wgWhitelistRead as $item )
134 if ( preg_match( '/^'.$item.'$/', $name )
135 || preg_match( '/^'.$dbName.'$/', $name ) ) return true;
136 ----
137
138
139 [[usage]]
140 == Usage
141
142 To use the changes we just put in place, all that needs to be done is edit the
143 $wgWhitelistRead variable in LocalSettings.php again.
144
145 Say, for example, that we have a 'HowTo' namespace ('HowTo:Drink Green Tea' for
146 example) that we want everyone to be able to read that isn't in the greentea
147 group (they have to learn somehow after all). All that needs to be done is a
148 little regex...
149
150 ----
151 $wgWhitelistRead = array(
152 'Main Page',
153 'Special:Userlogin',
154 'Special:UserLogout',
155 'HowTo:.*',
156 );
157 ----
158
159 That just whitelisted all pages inside the 'HowTo' namespace.
160
161
162 [[a-bad-explanation-attempt]]
163 == A Bad Explanation Attempt
164
165 In case anyone who doesn't know is wondering why you put a *.** at the end of
166 the HowTo namespace, here you go.
167
168 In regular expressions, various symbols have different meanings. In this case,
169 the period signifies any case letter, number, symbol, etc. That means that
170 'HowTo:.' would match anything like 'HowTo:A', 'HowTo:3', 'HowTo:-', etc. It
171 would however not match 'HowTo:A123'. Why? The period in regular expressions
172 matches only one character. What we need is to say match any character any
173 number of times after 'HowTo:'. For that we'll need the asterisk.
174
175 The asterisk in regular expressions is what we call a quantifier. It doesn't
176 represent a character so much as a quantity. In non regex terms, an asterisk
177 means that the previous character in the regex string can be repeated zero or
178 more times and still match. That means that the regular expression 'c*' would
179 match nothing, 'c', 'cccc', 'cccccc', etc. It would however not match for
180 example, 'b', '5', '12345a', etc. In our example, 'HowTo:.*', the period
181 represents any character and it is followed by an asterisk, so that means that
182 any article that starts with 'HowTo:' will match, no matter what the ending,
183 even if it doesn't have one.
184
185 Hopefully someone finds this post useful. If anyone has questions about *.**
186 please ask them in the comments.
187
188
189 // vim: set syntax=asciidoc:
|