1<?php
2
3namespace dokuwiki\plugin\aclplusregex\test;
4
5/**
6 * Tests for the aclplusregex plugin
7 *
8 * @group plugin_aclplusregex
9 * @group plugins
10 */
11class AclTest extends \DokuWikiTest
12{
13    protected $pluginsEnabled = ['aclplusregex'];
14
15    /**
16     * @return array
17     * @see testFullChain
18     */
19    public function providerFullChain()
20    {
21        return [
22            [
23                'users:foo:bar',
24                'john',
25                ['foo', '12345-doku-l1'],
26                false,
27            ],
28            [
29                'users:j:john:my:page',
30                'john',
31                ['foo', '12345-doku-l1'],
32                16,
33            ],
34            [
35                'kunden:12345:nosecret',
36                'john',
37                ['foo', '12345-doku-l1'],
38                1,
39            ],
40            [
41                'kunden:12345:intern',
42                'john',
43                ['foo', '12345-doku-l1'],
44                0,
45            ],
46            [
47                'kunden:12345:intern:secret',
48                'john',
49                ['foo', '12345-doku-l1'],
50                0,
51            ],
52            [
53                'kunden:12345:intern:secret',
54                'james',
55                ['foo', '12345-doku-l1', '12345-doku-intern-l3'],
56                16,
57            ],
58        ];
59    }
60
61    /**
62     * Run a full check on the result our system should deliver for the given names
63     *
64     * Testing happens against _test/conf/aclplusregex.conf
65     *
66     * @dataProvider providerFullChain
67     * @param string $id
68     * @param string $user
69     * @param string[] $groups
70     * @param int|false $expected
71     */
72    public function testFullChain($id, $user, $groups, $expected)
73    {
74        $act = new TestAction();
75
76        $this->assertSame(
77            $expected,
78            $act->evaluateRegex(
79                $act->rulesToRegex(
80                    $act->loadACLRules($user, $groups)
81                ),
82                $id
83            )
84        );
85    }
86
87    /**
88     * @return array
89     * @see testFullChainNsRegex
90     */
91    public function providerFullChainNsRegex()
92    {
93        return [
94            [
95                'reg:12345:678:sub',
96                'joshua',
97                ['foo', '12345-doku-sub-r1'],
98                4,
99            ],
100            [
101                'reg:12345:sub-678:sub',
102                'joshua',
103                ['foo', '12345-doku-bus-sub-r2'],
104                16,
105            ],
106            [
107                'reg:12345:sub-678:bus',
108                'joshua',
109                ['foo', '12345-doku-bus-sub-r2'],
110                2,
111            ],
112            [
113                'reg:12345:sub-90:sub',
114                'joshua',
115                ['foo', '12345-doku-bus-sub-r3'],
116                8,
117            ],
118            [
119                'reg:12345:sub-90:bus',
120                'joshua',
121                ['foo', '12345-doku-bus-sub-r3'],
122                1,
123            ],
124        ];
125    }
126
127    /**
128     * Run a full check on the result our system should deliver for the given names
129     *
130     * Testing happens against _test/conf/aclplusregex.conf
131     *
132     * @dataProvider providerFullChainNsRegex
133     * @param string $id
134     * @param string $user
135     * @param string[] $groups
136     * @param int|false $expected
137     */
138    public function testFullChainNsRegex($id, $user, $groups, $expected)
139    {
140        $act = new TestAction();
141
142        $this->assertSame(
143            $expected,
144            $act->evaluateRegex(
145                $act->rulesToRegex(
146                    $act->loadACLRules($user, $groups)
147                ),
148                $id
149            )
150        );
151    }
152
153    /**
154     * @return array (entities, id, pattern, expected)
155     * @see testGetIdPatterns
156     */
157    public function providerGetIdPatterns()
158    {
159        $entities = ['user_name', '@987654_matching', '@non-matching-group', '@123456_matching'];
160
161        return [
162            [
163                $entities,
164                'customers:$1:*',
165                '@(\d{6})_.*',
166                [
167                    'customers:987654:*',
168                    'customers:123456:*',
169                ],
170            ],
171            [
172                $entities,
173                'user:$1:**',
174                '(.*)',
175                [
176                    'user:user_name:**',
177                ],
178            ],
179            [
180                ['user name'], // clean the space in the name
181                'user:$1:**',
182                '(.*)',
183                [
184                    'user:user_name:**',
185                ],
186            ],
187        ];
188    }
189
190    /**
191     * Test some individual patterns and users
192     *
193     * @dataProvider providerGetIdPatterns
194     */
195    public function testGetIdPatterns($entities, $id, $pattern, $expected)
196    {
197        $act = new TestAction();
198        $this->assertEquals($expected, $act->getIDPatterns($entities, $id, $pattern));
199    }
200
201    /**
202     * @return array (user, groups, expect)
203     * @see testLoadACLRules
204     */
205    public function providerLoadACLRules()
206    {
207        return [
208            [ // user rule only for a J user
209              'john',
210              ['foo'],
211              ['users:j:john:**' => 16],
212            ],
213            [ // user rule only for a non-J user
214              'harry',
215              ['foo'],
216              ['users:j:harry:**' => 4],
217            ],
218            [ // J-User with a matching group
219              'john',
220              ['12345-doku-l2'],
221              [
222                  'users:j:john:**' => 16,
223                  'kunden:12345:intern:**' => 0,
224                  'kunden:12345:intern' => 0,
225                  'kunden:12345:**' => 2,
226              ],
227            ],
228            [ // J-User with two matching groups that result in overlapping rules
229              'john',
230              ['12345-doku-l2', '12345-doku-l3'],
231              [
232                  'users:j:john:**' => 16,
233                  'kunden:12345:intern:**' => 0,
234                  'kunden:12345:intern' => 0,
235                  'kunden:12345:**' => 16,
236              ],
237            ],
238            [ // user rule with a fancy user name
239              'Harry Belafonte',
240              ['foo'],
241              ['users:j:harry_belafonte:**' => 4],
242            ],
243        ];
244    }
245
246    /**
247     * Test loading ACL rules for different users
248     *
249     * Testing happens against _test/conf/aclplusregex.conf
250     *
251     * @dataProvider providerLoadACLRules
252     * @param string $user
253     * @param string[] $groups
254     * @param array $expect
255     */
256    public function testLoadACLRules($user, $groups, $expect)
257    {
258        $act = new TestAction();
259        $this->assertEquals($expect, $act->loadACLRules($user, $groups));
260    }
261
262    /**
263     * @return array (rules, expect)
264     * @see testSortRules
265     */
266    public function providerSortRules()
267    {
268        return [
269            [
270                [
271                    'this:is:longer' => 1,
272                    'this:is:longer:even' => 1,
273                    'this:short' => 1,
274                    'this' => 1,
275                ],
276                [
277                    'this:is:longer:even' => 1,
278                    'this:is:longer' => 1,
279                    'this:short' => 1,
280                    'this' => 1,
281                ],
282            ],
283            [
284                [
285                    'kunden:12345:intern:**' => 1,
286                    'kunden:12345:**' => 1,
287                    'kunden:12345:intern' => 1,
288                ],
289                [
290                    'kunden:12345:intern' => 1,
291                    'kunden:12345:intern:**' => 1,
292                    'kunden:12345:**' => 1,
293                ],
294            ],
295            [
296                [
297                    'this:has:three' => 1,
298                    'this:twoverylongthing' => 1,
299                    'this:has:three:four' => 1,
300                    'same:**' => 1,
301                    'same:*' => 1,
302                    'same:foo' => 1,
303                    'aaaaaaaa:one' => 1,
304                    'zz' => 1,
305                    'aa' => 1,
306                ],
307                [
308                    'aa' => 1,
309                    'aaaaaaaa:one' => 1,
310                    'same:foo' => 1,
311                    'same:*' => 1,
312                    'same:**' => 1,
313                    'this:has:three:four' => 1,
314                    'this:has:three' => 1,
315                    'this:twoverylongthing' => 1,
316                    'zz' => 1,
317                ],
318            ],
319            [
320                [
321                    'reg:12345:(sub-\d{3}):sub' => 1,
322                    'reg:12345:(sub-\d{3}):*' => 1,
323                    'reg:12345:sub-678:bus' => 1,
324                ],
325                [
326                    'reg:12345:sub-678:bus' => 1,
327                    'reg:12345:(sub-\d{3}):sub' => 1,
328                    'reg:12345:(sub-\d{3}):*' => 1,
329                ],
330            ],
331        ];
332    }
333
334    /**
335     * Test that rules are sorted correctly
336     *
337     * @dataProvider providerSortRules
338     * @param array $rules
339     * @param array $expect
340     */
341    public function testSortRules($rules, $expect)
342    {
343        $act = new TestAction();
344
345        $this->assertSame(
346            $expect,
347            $act->sortRules($rules)
348        );
349    }
350
351    public function testPatternToRegexGroup()
352    {
353        $acl = new TestAction();
354
355        $this->assertEquals(
356            '(?<g0x4>foo:' . TestAction::STARS . ')',
357            $acl->patternToRegexGroup('foo:**', 4)
358        );
359
360        $this->assertEquals(
361            '(?<g1x4>foo:' . TestAction::STAR . ')',
362            $acl->patternToRegexGroup('foo:*', 4)
363        );
364
365        $this->assertEquals(
366            '(?<g2x4>foo:' . TestAction::STAR . ':' . TestAction::STARS . ')',
367            $acl->patternToRegexGroup('foo:*:**', 4)
368        );
369
370    }
371}
372