xref: /OpenGrok/plugins/src/test/java/opengrok/auth/plugin/UserWhiteListPluginTest.java (revision 4ceb1b98c17b7b580c0718bb27573b95081b34a5)
1895b87d2SChris Fraire /*
2895b87d2SChris Fraire  * CDDL HEADER START
3895b87d2SChris Fraire  *
4895b87d2SChris Fraire  * The contents of this file are subject to the terms of the
5895b87d2SChris Fraire  * Common Development and Distribution License (the "License").
6895b87d2SChris Fraire  * You may not use this file except in compliance with the License.
7895b87d2SChris Fraire  *
8895b87d2SChris Fraire  * See LICENSE.txt included in this distribution for the specific
9895b87d2SChris Fraire  * language governing permissions and limitations under the License.
10895b87d2SChris Fraire  *
11895b87d2SChris Fraire  * When distributing Covered Code, include this CDDL HEADER in each
12895b87d2SChris Fraire  * file and include the License file at LICENSE.txt.
13895b87d2SChris Fraire  * If applicable, add the following below this CDDL HEADER, with the
14895b87d2SChris Fraire  * fields enclosed by brackets "[]" replaced with your own identifying
15895b87d2SChris Fraire  * information: Portions Copyright [yyyy] [name of copyright owner]
16895b87d2SChris Fraire  *
17895b87d2SChris Fraire  * CDDL HEADER END
18895b87d2SChris Fraire  */
19895b87d2SChris Fraire 
20895b87d2SChris Fraire /*
21895b87d2SChris Fraire  * Copyright (c) 2020, Chris Fraire <cfraire@me.com>.
222f7dccc7SAdam Hornacek  * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
23895b87d2SChris Fraire  */
24895b87d2SChris Fraire package opengrok.auth.plugin;
25895b87d2SChris Fraire 
26895b87d2SChris Fraire import opengrok.auth.plugin.entity.User;
276c62ede9SAdam Hornacek import org.apache.commons.lang3.RandomStringUtils;
282f7dccc7SAdam Hornacek import org.junit.jupiter.api.AfterAll;
292f7dccc7SAdam Hornacek import org.junit.jupiter.api.BeforeAll;
302f7dccc7SAdam Hornacek import org.junit.jupiter.params.ParameterizedTest;
312f7dccc7SAdam Hornacek import org.junit.jupiter.params.provider.MethodSource;
32895b87d2SChris Fraire import org.opengrok.indexer.configuration.Group;
33895b87d2SChris Fraire import org.opengrok.indexer.configuration.Project;
34895b87d2SChris Fraire import org.opengrok.indexer.web.DummyHttpServletRequest;
35895b87d2SChris Fraire 
36895b87d2SChris Fraire import java.io.BufferedWriter;
37895b87d2SChris Fraire import java.io.File;
38895b87d2SChris Fraire import java.io.FileOutputStream;
39ee1fba58SVladimir Kotal import java.io.IOException;
40895b87d2SChris Fraire import java.io.OutputStreamWriter;
41ee1fba58SVladimir Kotal import java.io.PrintWriter;
42895b87d2SChris Fraire import java.nio.charset.StandardCharsets;
43ee1fba58SVladimir Kotal import java.nio.file.Files;
441f3b8d68SVladimir Kotal import java.util.Arrays;
451f3b8d68SVladimir Kotal import java.util.Collection;
46895b87d2SChris Fraire import java.util.HashMap;
472f7dccc7SAdam Hornacek import java.util.Map;
48ee1fba58SVladimir Kotal import java.util.Set;
49ee1fba58SVladimir Kotal import java.util.stream.Collectors;
50ee1fba58SVladimir Kotal import java.util.stream.Stream;
51895b87d2SChris Fraire 
52ee1fba58SVladimir Kotal import static org.junit.jupiter.api.Assertions.assertEquals;
532f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertFalse;
542f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertNotNull;
55895b87d2SChris Fraire import static org.junit.jupiter.api.Assertions.assertThrows;
562f7dccc7SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertTrue;
57895b87d2SChris Fraire 
58895b87d2SChris Fraire /**
59895b87d2SChris Fraire  * Represents a container for tests of {@link UserWhiteListPlugin}.
60895b87d2SChris Fraire  */
61895b87d2SChris Fraire public class UserWhiteListPluginTest {
62895b87d2SChris Fraire 
63895b87d2SChris Fraire     private static final String OK_USER = "user1321";
641f3b8d68SVladimir Kotal     private static final String OK_ID = "id2178";
651f3b8d68SVladimir Kotal     private static File tempWhitelistUser;
661f3b8d68SVladimir Kotal     private static File tempWhitelistId;
67895b87d2SChris Fraire     private static HashMap<String, Object> validPluginParameters;
68895b87d2SChris Fraire 
69895b87d2SChris Fraire     private UserWhiteListPlugin plugin;
701f3b8d68SVladimir Kotal 
parameters()711f3b8d68SVladimir Kotal     public static Collection<String> parameters() {
721f3b8d68SVladimir Kotal         return Arrays.asList(UserWhiteListPlugin.ID_FIELD, UserWhiteListPlugin.USERNAME_FIELD);
731f3b8d68SVladimir Kotal     }
741f3b8d68SVladimir Kotal 
752f7dccc7SAdam Hornacek     @BeforeAll
beforeClass()76895b87d2SChris Fraire     public static void beforeClass() throws Exception {
771f3b8d68SVladimir Kotal         tempWhitelistUser = File.createTempFile("UserWhiteListPluginTestUser", "txt");
78895b87d2SChris Fraire         try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
791f3b8d68SVladimir Kotal                 new FileOutputStream(tempWhitelistUser), StandardCharsets.UTF_8))) {
80895b87d2SChris Fraire             writer.write(OK_USER);
81895b87d2SChris Fraire             // Don't bother with trailing LF.
82895b87d2SChris Fraire         }
83895b87d2SChris Fraire 
841f3b8d68SVladimir Kotal         tempWhitelistId = File.createTempFile("UserWhiteListPluginTestId", "txt");
851f3b8d68SVladimir Kotal         try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
861f3b8d68SVladimir Kotal                 new FileOutputStream(tempWhitelistId), StandardCharsets.UTF_8))) {
871f3b8d68SVladimir Kotal             writer.write(OK_ID);
881f3b8d68SVladimir Kotal             // Don't bother with trailing LF.
891f3b8d68SVladimir Kotal         }
901f3b8d68SVladimir Kotal 
91895b87d2SChris Fraire         validPluginParameters = new HashMap<>();
92895b87d2SChris Fraire     }
93895b87d2SChris Fraire 
942f7dccc7SAdam Hornacek     @AfterAll
afterClass()95895b87d2SChris Fraire     public static void afterClass() {
961f3b8d68SVladimir Kotal         if (tempWhitelistUser != null) {
97895b87d2SChris Fraire             //noinspection ResultOfMethodCallIgnored
981f3b8d68SVladimir Kotal             tempWhitelistUser.delete();
991f3b8d68SVladimir Kotal         }
1001f3b8d68SVladimir Kotal         if (tempWhitelistId != null) {
1011f3b8d68SVladimir Kotal             //noinspection ResultOfMethodCallIgnored
1021f3b8d68SVladimir Kotal             tempWhitelistId.delete();
103895b87d2SChris Fraire         }
104895b87d2SChris Fraire     }
105895b87d2SChris Fraire 
init(String param)1062f7dccc7SAdam Hornacek     public void init(String param) {
107895b87d2SChris Fraire         plugin = new UserWhiteListPlugin();
1082f7dccc7SAdam Hornacek         validPluginParameters.put(UserWhiteListPlugin.FIELD_PARAM, param);
1092f7dccc7SAdam Hornacek         if (param.equals(UserWhiteListPlugin.USERNAME_FIELD)) {
1101f3b8d68SVladimir Kotal             validPluginParameters.put(UserWhiteListPlugin.FILE_PARAM, tempWhitelistUser.getPath());
1111f3b8d68SVladimir Kotal         } else {
1121f3b8d68SVladimir Kotal             validPluginParameters.put(UserWhiteListPlugin.FILE_PARAM, tempWhitelistId.getPath());
1131f3b8d68SVladimir Kotal         }
114895b87d2SChris Fraire     }
115895b87d2SChris Fraire 
1162f7dccc7SAdam Hornacek     @ParameterizedTest
1172f7dccc7SAdam Hornacek     @MethodSource("parameters")
shouldThrowOnLoadIfNullArgument(String param)1182f7dccc7SAdam Hornacek     public void shouldThrowOnLoadIfNullArgument(String param) {
1192f7dccc7SAdam Hornacek         init(param);
120*4ceb1b98SVladimir Kotal         assertThrows(IllegalArgumentException.class, () -> {
121895b87d2SChris Fraire             //noinspection ConstantConditions
122895b87d2SChris Fraire             plugin.load(null);
123895b87d2SChris Fraire             }, "plugin.load(null)");
124895b87d2SChris Fraire     }
125895b87d2SChris Fraire 
1262f7dccc7SAdam Hornacek     @ParameterizedTest
1272f7dccc7SAdam Hornacek     @MethodSource("parameters")
shouldThrowOnLoadIfInvalidFieldName(String param)1282f7dccc7SAdam Hornacek     public void shouldThrowOnLoadIfInvalidFieldName(String param) {
1292f7dccc7SAdam Hornacek         init(param);
1301f3b8d68SVladimir Kotal         assertThrows(IllegalArgumentException.class, () -> {
1312f7dccc7SAdam Hornacek             Map<String, Object> map = new HashMap<>();
1321f3b8d68SVladimir Kotal             map.put(UserWhiteListPlugin.FILE_PARAM, tempWhitelistUser.getPath());
1331f3b8d68SVladimir Kotal             map.put(UserWhiteListPlugin.FIELD_PARAM, "huh");
1341f3b8d68SVladimir Kotal             plugin.load(map);
1351f3b8d68SVladimir Kotal         }, "plugin.load(null)");
1361f3b8d68SVladimir Kotal     }
1371f3b8d68SVladimir Kotal 
1382f7dccc7SAdam Hornacek     @ParameterizedTest
1392f7dccc7SAdam Hornacek     @MethodSource("parameters")
shouldThrowOnLoadIfUnreadableFileSpecified(String param)1402f7dccc7SAdam Hornacek     public void shouldThrowOnLoadIfUnreadableFileSpecified(String param) {
1412f7dccc7SAdam Hornacek         init(param);
142895b87d2SChris Fraire         HashMap<String, Object> unreadablePluginParameters = new HashMap<>();
143895b87d2SChris Fraire         unreadablePluginParameters.put(UserWhiteListPlugin.FILE_PARAM,
1446c62ede9SAdam Hornacek                 RandomStringUtils.randomAlphanumeric(24));
145895b87d2SChris Fraire 
146895b87d2SChris Fraire         IllegalArgumentException caughtException = null;
147895b87d2SChris Fraire         try {
148895b87d2SChris Fraire             plugin.load(unreadablePluginParameters);
149895b87d2SChris Fraire         } catch (IllegalArgumentException ex) {
150895b87d2SChris Fraire             caughtException = ex;
151895b87d2SChris Fraire         }
152895b87d2SChris Fraire 
1532f7dccc7SAdam Hornacek         assertNotNull(caughtException, "caught IllegalArgumentException");
1542f7dccc7SAdam Hornacek         assertTrue(caughtException.getMessage().contains("Unable to read the file"),
1552f7dccc7SAdam Hornacek                 "caughtException should mention 'Unable to read the file'");
156895b87d2SChris Fraire     }
157895b87d2SChris Fraire 
1582f7dccc7SAdam Hornacek     @ParameterizedTest
1592f7dccc7SAdam Hornacek     @MethodSource("parameters")
shouldThrowOnLoadIfNoFileSpecified(String param)1602f7dccc7SAdam Hornacek     public void shouldThrowOnLoadIfNoFileSpecified(String param) {
1612f7dccc7SAdam Hornacek         init(param);
162895b87d2SChris Fraire         IllegalArgumentException caughtException = null;
163895b87d2SChris Fraire         try {
164895b87d2SChris Fraire             plugin.load(new HashMap<>());
165895b87d2SChris Fraire         } catch (IllegalArgumentException ex) {
166895b87d2SChris Fraire             caughtException = ex;
167895b87d2SChris Fraire         }
168895b87d2SChris Fraire 
1692f7dccc7SAdam Hornacek         assertNotNull(caughtException, "caught IllegalArgumentException");
1702f7dccc7SAdam Hornacek         assertTrue(caughtException.getMessage().contains("Missing parameter"),
1712f7dccc7SAdam Hornacek                 "caughtException should mention 'Missing parameter'");
172895b87d2SChris Fraire     }
173895b87d2SChris Fraire 
1742f7dccc7SAdam Hornacek     @ParameterizedTest
1752f7dccc7SAdam Hornacek     @MethodSource("parameters")
shouldStripWhitespaceFromWhitelists(String param)176ee1fba58SVladimir Kotal     public void shouldStripWhitespaceFromWhitelists(String param) throws IOException {
177ee1fba58SVladimir Kotal         plugin = new UserWhiteListPlugin();
178ee1fba58SVladimir Kotal         HashMap<String, Object> pluginParameters = new HashMap<>();
179ee1fba58SVladimir Kotal         pluginParameters.put(UserWhiteListPlugin.FIELD_PARAM, param);
180ee1fba58SVladimir Kotal         Set<String> entries = Set.of("Moomin", " Fillyjonk", "  Snuffkin", "Snork Maiden  ", "Groke ");
181ee1fba58SVladimir Kotal 
182ee1fba58SVladimir Kotal         File tmpFile = File.createTempFile("UserWhiteListPluginTestId", "txt");
183ee1fba58SVladimir Kotal         try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(
184ee1fba58SVladimir Kotal                 new FileOutputStream(tmpFile), StandardCharsets.UTF_8))) {
185ee1fba58SVladimir Kotal             for (String entity : entries) {
186ee1fba58SVladimir Kotal                 writer.println(entity);
187ee1fba58SVladimir Kotal             }
188ee1fba58SVladimir Kotal         }
189ee1fba58SVladimir Kotal 
190ee1fba58SVladimir Kotal         // Make sure there as some entries with trailing spaces in the file.
191ee1fba58SVladimir Kotal         Stream<String> stream = Files.lines(tmpFile.toPath());
192ee1fba58SVladimir Kotal         assertTrue(stream.filter(s -> s.startsWith(" ") || s.endsWith(" ")).
193ee1fba58SVladimir Kotal                 collect(Collectors.toSet()).size() > 0);
194ee1fba58SVladimir Kotal 
195ee1fba58SVladimir Kotal         pluginParameters.put(UserWhiteListPlugin.FILE_PARAM, tmpFile.toString());
196ee1fba58SVladimir Kotal         plugin.load(pluginParameters);
197ee1fba58SVladimir Kotal         tmpFile.delete();
198ee1fba58SVladimir Kotal 
199ee1fba58SVladimir Kotal         Set<String> expected = entries.stream().map(String::trim).collect(Collectors.toSet());
200ee1fba58SVladimir Kotal         assertEquals(expected, plugin.getWhitelist());
201ee1fba58SVladimir Kotal     }
202ee1fba58SVladimir Kotal 
203ee1fba58SVladimir Kotal     @ParameterizedTest
204ee1fba58SVladimir Kotal     @MethodSource("parameters")
shouldUnload(String param)2052f7dccc7SAdam Hornacek     public void shouldUnload(String param) {
2062f7dccc7SAdam Hornacek         init(param);
207895b87d2SChris Fraire         plugin.unload();
208895b87d2SChris Fraire     }
209895b87d2SChris Fraire 
2102f7dccc7SAdam Hornacek     @ParameterizedTest
2112f7dccc7SAdam Hornacek     @MethodSource("parameters")
shouldAllowWhitelistedUserForAnyProject(String param)2122f7dccc7SAdam Hornacek     public void shouldAllowWhitelistedUserForAnyProject(String param) {
2132f7dccc7SAdam Hornacek         init(param);
214895b87d2SChris Fraire         plugin.load(validPluginParameters);
215895b87d2SChris Fraire 
216895b87d2SChris Fraire         DummyHttpServletRequest req = new DummyHttpServletRequest();
2171f3b8d68SVladimir Kotal         User user;
2182f7dccc7SAdam Hornacek         if (param.equals(UserWhiteListPlugin.USERNAME_FIELD)) {
2191f3b8d68SVladimir Kotal             user = new User(OK_USER);
2201f3b8d68SVladimir Kotal         } else {
2211f3b8d68SVladimir Kotal             user = new User("blurb", OK_ID);
2221f3b8d68SVladimir Kotal         }
2231f3b8d68SVladimir Kotal         req.setAttribute(UserPlugin.REQUEST_ATTR, user);
224895b87d2SChris Fraire 
2256c62ede9SAdam Hornacek         Project randomProject = new Project(RandomStringUtils.randomAlphanumeric(10));
226895b87d2SChris Fraire         boolean projectAllowed = plugin.isAllowed(req, randomProject);
2272f7dccc7SAdam Hornacek         assertTrue(projectAllowed, "should allow OK entity for random project 1");
228895b87d2SChris Fraire 
2296c62ede9SAdam Hornacek         randomProject = new Project(RandomStringUtils.randomAlphanumeric(10));
230895b87d2SChris Fraire         projectAllowed = plugin.isAllowed(req, randomProject);
2312f7dccc7SAdam Hornacek         assertTrue(projectAllowed, "should allow OK entity for random project 2");
232895b87d2SChris Fraire     }
233895b87d2SChris Fraire 
2342f7dccc7SAdam Hornacek     @ParameterizedTest
2352f7dccc7SAdam Hornacek     @MethodSource("parameters")
shouldNotAllowRandomUserForAnyProject(String param)2362f7dccc7SAdam Hornacek     public void shouldNotAllowRandomUserForAnyProject(String param) {
2372f7dccc7SAdam Hornacek         init(param);
238895b87d2SChris Fraire         plugin.load(validPluginParameters);
239895b87d2SChris Fraire 
240895b87d2SChris Fraire         DummyHttpServletRequest req = new DummyHttpServletRequest();
2416c62ede9SAdam Hornacek         req.setAttribute(UserPlugin.REQUEST_ATTR, new User(RandomStringUtils.randomAlphanumeric(8)));
242895b87d2SChris Fraire 
2436c62ede9SAdam Hornacek         Project randomProject = new Project(RandomStringUtils.randomAlphanumeric(10));
244895b87d2SChris Fraire         boolean projectAllowed = plugin.isAllowed(req, randomProject);
2452f7dccc7SAdam Hornacek         assertFalse(projectAllowed, "should not allow random user for random project 1");
246895b87d2SChris Fraire 
2476c62ede9SAdam Hornacek         randomProject = new Project(RandomStringUtils.randomAlphanumeric(10));
248895b87d2SChris Fraire         projectAllowed = plugin.isAllowed(req, randomProject);
2492f7dccc7SAdam Hornacek         assertFalse(projectAllowed, "should not allow random user for random project 2");
250895b87d2SChris Fraire     }
251895b87d2SChris Fraire 
2522f7dccc7SAdam Hornacek     @ParameterizedTest
2532f7dccc7SAdam Hornacek     @MethodSource("parameters")
shouldAllowWhitelistedUserForAnyGroup(String param)2542f7dccc7SAdam Hornacek     public void shouldAllowWhitelistedUserForAnyGroup(String param) {
2552f7dccc7SAdam Hornacek         init(param);
256895b87d2SChris Fraire         plugin.load(validPluginParameters);
257895b87d2SChris Fraire 
258895b87d2SChris Fraire         DummyHttpServletRequest req = new DummyHttpServletRequest();
2591f3b8d68SVladimir Kotal         User user;
2602f7dccc7SAdam Hornacek         if (param.equals(UserWhiteListPlugin.USERNAME_FIELD)) {
2611f3b8d68SVladimir Kotal             user = new User(OK_USER);
2621f3b8d68SVladimir Kotal         } else {
2631f3b8d68SVladimir Kotal             user = new User("blurb", OK_ID);
2641f3b8d68SVladimir Kotal         }
2651f3b8d68SVladimir Kotal         req.setAttribute(UserPlugin.REQUEST_ATTR, user);
266895b87d2SChris Fraire 
2676c62ede9SAdam Hornacek         Group randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10));
268895b87d2SChris Fraire         boolean groupAllowed = plugin.isAllowed(req, randomGroup);
2692f7dccc7SAdam Hornacek         assertTrue(groupAllowed, "should allow OK entity for random group 1");
270895b87d2SChris Fraire 
2716c62ede9SAdam Hornacek         randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10));
272895b87d2SChris Fraire         groupAllowed = plugin.isAllowed(req, randomGroup);
2732f7dccc7SAdam Hornacek         assertTrue(groupAllowed, "should allow OK entity for random group 2");
274895b87d2SChris Fraire     }
275895b87d2SChris Fraire 
2762f7dccc7SAdam Hornacek     @ParameterizedTest
2772f7dccc7SAdam Hornacek     @MethodSource("parameters")
shouldNotAllowRandomUserForAnyGroup(String param)2782f7dccc7SAdam Hornacek     public void shouldNotAllowRandomUserForAnyGroup(String param) {
2792f7dccc7SAdam Hornacek         init(param);
280895b87d2SChris Fraire         plugin.load(validPluginParameters);
281895b87d2SChris Fraire 
282895b87d2SChris Fraire         DummyHttpServletRequest req = new DummyHttpServletRequest();
2836c62ede9SAdam Hornacek         req.setAttribute(UserPlugin.REQUEST_ATTR, new User(RandomStringUtils.randomAlphanumeric(8)));
284895b87d2SChris Fraire 
2856c62ede9SAdam Hornacek         Group randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10));
286895b87d2SChris Fraire         boolean projectAllowed = plugin.isAllowed(req, randomGroup);
2872f7dccc7SAdam Hornacek         assertFalse(projectAllowed, "should not allow random group 1");
288895b87d2SChris Fraire 
2896c62ede9SAdam Hornacek         randomGroup = new Group(RandomStringUtils.randomAlphanumeric(10));
290895b87d2SChris Fraire         projectAllowed = plugin.isAllowed(req, randomGroup);
2912f7dccc7SAdam Hornacek         assertFalse(projectAllowed, "should not allow random group 2");
292895b87d2SChris Fraire     }
293895b87d2SChris Fraire }
294