Skip to content

Commit 70d510d

Browse files
tulinkryVladimir Kotal
authored andcommitted
group parameter for search URL (#2507)
approaches #1974
1 parent c0d81b8 commit 70d510d

File tree

2 files changed

+253
-43
lines changed

2 files changed

+253
-43
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/web/PageConfig.java

Lines changed: 73 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
*/
2525
package org.opengrok.indexer.web;
2626

27+
import static org.opengrok.indexer.index.Indexer.PATH_SEPARATOR;
28+
import static org.opengrok.indexer.index.Indexer.PATH_SEPARATOR_STRING;
29+
2730
import java.io.BufferedReader;
2831
import java.io.File;
2932
import java.io.FileNotFoundException;
@@ -75,9 +78,6 @@
7578
import org.suigeneris.jrcs.diff.Diff;
7679
import org.suigeneris.jrcs.diff.DifferentiationFailedException;
7780

78-
import static org.opengrok.indexer.index.Indexer.PATH_SEPARATOR;
79-
import static org.opengrok.indexer.index.Indexer.PATH_SEPARATOR_STRING;
80-
8181
/**
8282
* A simple container to lazy initialize common vars wrt. a single request. It
8383
* MUST NOT be shared between several requests and
@@ -101,8 +101,10 @@ public final class PageConfig {
101101

102102
private static final Logger LOGGER = LoggerFactory.getLogger(PageConfig.class);
103103

104-
public static final String OPEN_GROK_PROJECT = "OpenGrokProject";
105-
104+
protected static final String OPEN_GROK_PROJECT = "OpenGrokProject";
105+
protected static final String PROJECT_PARAM_NAME = "project";
106+
protected static final String GROUP_PARAM_NAME = "group";
107+
106108
// TODO if still used, get it from the app context
107109

108110
private final AuthorizationFramework authFramework;
@@ -794,24 +796,33 @@ public String getRequestedProjectsAsString() {
794796
* <p>
795797
* NOTE: This method assumes, that project names do <b>not</b> contain a
796798
* comma (','), since this character is used as name separator!
799+
* <p>
800+
* It is determined as follows:
801+
* <ol>
802+
* <li>If there is no project in the configuration an empty set is returned. Otherwise:</li>
803+
* <li>If there is only one project in the configuration,
804+
* this one gets returned (no matter, what the request actually says). Otherwise</li>
805+
* <li>If the request parameter {@code PROJECT_PARAM_NAME} contains any available project,
806+
* the set with invalid projects removed gets returned. Otherwise:</li>
807+
* <li>If the request parameter {@code GROUP_PARAM_NAME} contains any available group,
808+
* then all projects from that group will be added to the result set. Otherwise:</li>
809+
* <li>If the request has a cookie with the name {@code OPEN_GROK_PROJECT}
810+
* and it contains any available project,
811+
* the set with invalid projects removed gets returned. Otherwise:</li>
812+
* <li>If a default project is set in the configuration,
813+
* this project gets returned. Otherwise:</li>
814+
* <li>an empty set</li>
815+
* </ol>
797816
*
798-
* @return a possible empty set of project names but never
799-
* {@code null}. It is determined as follows: <ol> <li>If there is no
800-
* project in the runtime environment (RTE) an empty set is returned.
801-
* Otherwise:</li> <li>If there is only one project in the RTE, this one
802-
* gets returned (no matter, what the request actually says). Otherwise</li>
803-
* <li>If the request parameter {@code project} contains any available
804-
* project, the set with invalid projects removed gets returned.
805-
* Otherwise:</li> <li>If the request has a cookie with the name
806-
* {@code OpenGrokProject} and it contains any available project, the set
807-
* with invalid projects removed gets returned. Otherwise:</li> <li>If a
808-
* default project is set in the RTE, this project gets returned.
809-
* Otherwise:</li> <li>an empty set</li> </ol>
817+
* @return a possible empty set of project names but never {@code null}.
818+
* @see #PROJECT_PARAM_NAME
819+
* @see #GROUP_PARAM_NAME
820+
* @see #OPEN_GROK_PROJECT
810821
*/
811822
public SortedSet<String> getRequestedProjects() {
812823
if (requestedProjects == null) {
813824
requestedProjects
814-
= getRequestedProjects("project", OPEN_GROK_PROJECT);
825+
= getRequestedProjects(PROJECT_PARAM_NAME, GROUP_PARAM_NAME, OPEN_GROK_PROJECT);
815826
}
816827
return requestedProjects;
817828
}
@@ -875,71 +886,90 @@ private List<String> getParamVals(String paramName) {
875886

876887
/**
877888
* Same as {@link #getRequestedProjects()}, but with a variable cookieName
878-
* and parameter name. This way it is trivial to implement a project filter
879-
* ...
889+
* and parameter name.
880890
*
881-
* @param paramName the name of the request parameter, which possibly
882-
* contains the project list in question.
883-
* @param cookieName name of the cookie which possible contains project
884-
* lists used as fallback
891+
* @param projectParamName the name of the request parameter corresponding to a project name.
892+
* @param groupParamName the name of the request parameter corresponding to a group name
893+
* @param cookieName name of the cookie which possible contains project
894+
* names used as fallback
885895
* @return set of project names. Possibly empty set but never {@code null}.
886896
*/
887-
protected SortedSet<String> getRequestedProjects(String paramName,
888-
String cookieName) {
897+
protected SortedSet<String> getRequestedProjects(
898+
String projectParamName,
899+
String groupParamName,
900+
String cookieName
901+
) {
889902

890-
TreeSet<String> set = new TreeSet<>();
903+
TreeSet<String> projectNames = new TreeSet<>();
891904
List<Project> projects = getEnv().getProjectList();
892905

893906
if (projects == null) {
894-
return set;
907+
return projectNames;
895908
}
896909

897910
/**
898-
* If the project was determined from the URL, use this project.
911+
* Use a project determined directly from the URL
899912
*/
900913
if (getProject() != null) {
901-
set.add(getProject().getName());
902-
return set;
914+
projectNames.add(getProject().getName());
915+
return projectNames;
903916
}
904917

918+
/**
919+
* Use a project if the application has only single project.
920+
*/
905921
if (projects.size() == 1) {
906922
Project p = projects.get(0);
907923
if (authFramework.isAllowed(req, p)) {
908-
set.add(p.getName());
924+
projectNames.add(p.getName());
909925
}
910-
return set;
926+
return projectNames;
911927
}
912928

913-
List<String> vals = getParamVals(paramName);
914-
for (String s : vals) {
915-
Project x = Project.getByName(s);
916-
if (x != null && authFramework.isAllowed(req, x)) {
917-
set.add(s);
929+
/**
930+
* Add all projects which match the project parameter name values
931+
*/
932+
List<String> names = getParamVals(projectParamName);
933+
for (String projectName : names) {
934+
Project project = Project.getByName(projectName);
935+
if (project != null && authFramework.isAllowed(req, project)) {
936+
projectNames.add(projectName);
937+
}
938+
}
939+
940+
/**
941+
* Add all projects which are part of a group that matches the group parameter name
942+
*/
943+
names = getParamVals(groupParamName);
944+
for (String groupName : names) {
945+
Group group = Group.getByName(groupName);
946+
if (group != null) {
947+
projectNames.addAll(getProjectHelper().getAllGrouped(group).stream().map(Project::getName).collect(Collectors.toSet()));
918948
}
919949
}
920950

921-
if (set.isEmpty()) {
951+
if (projectNames.isEmpty()) {
922952
List<String> cookies = getCookieVals(cookieName);
923953
for (String s : cookies) {
924954
Project x = Project.getByName(s);
925955
if (x != null && authFramework.isAllowed(req, x)) {
926-
set.add(s);
956+
projectNames.add(s);
927957
}
928958
}
929959
}
930960

931-
if (set.isEmpty()) {
961+
if (projectNames.isEmpty()) {
932962
Set<Project> defaultProjects = env.getDefaultProjects();
933963
if (defaultProjects != null) {
934964
for (Project project : defaultProjects) {
935965
if (authFramework.isAllowed(req, project)) {
936-
set.add(project.getName());
966+
projectNames.add(project.getName());
937967
}
938968
}
939969
}
940970
}
941971

942-
return set;
972+
return projectNames;
943973
}
944974

945975
public ProjectHelper getProjectHelper() {
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
package org.opengrok.indexer.web;
2+
3+
import java.util.Arrays;
4+
import java.util.HashSet;
5+
import java.util.Map;
6+
import java.util.Set;
7+
import java.util.TreeMap;
8+
import java.util.TreeSet;
9+
import javax.servlet.http.HttpServletRequest;
10+
import org.junit.After;
11+
import org.junit.Assert;
12+
import org.junit.Before;
13+
import org.junit.Test;
14+
import org.mockito.Mockito;
15+
import org.opengrok.indexer.authorization.AuthorizationStack;
16+
import org.opengrok.indexer.configuration.Group;
17+
import org.opengrok.indexer.configuration.Project;
18+
import org.opengrok.indexer.configuration.RuntimeEnvironment;
19+
20+
public class PageConfigRequestedProjectsTest {
21+
22+
final RuntimeEnvironment env = RuntimeEnvironment.getInstance();
23+
24+
private Map<String, Project> oldProjects;
25+
private Set<Group> oldGroups;
26+
private AuthorizationStack oldPluginStack;
27+
28+
@Before
29+
public void setUp() {
30+
oldProjects = env.getProjects();
31+
oldGroups = env.getGroups();
32+
oldPluginStack = env.getPluginStack();
33+
34+
Set<Group> groups = new TreeSet<>();
35+
Map<String, Project> projects = new TreeMap<>();
36+
37+
for (int i = 0; i < 10; i++) {
38+
Project project = new Project();
39+
project.setName("project-" + i);
40+
project.setPath("/project-" + i);
41+
project.setIndexed(true);
42+
43+
projects.put("project-" + i, project);
44+
}
45+
46+
Group group;
47+
group = new Group();
48+
group.setName("group-1-2-3");
49+
group.setPattern("project-(1|2|3)");
50+
groups.add(group);
51+
52+
group = new Group();
53+
group.setName("group-7-8-9");
54+
group.setPattern("project-(7|8|9)");
55+
groups.add(group);
56+
57+
env.setGroups(groups);
58+
env.setProjects(projects);
59+
env.setProjectsEnabled(true);
60+
env.setPluginStack(null);
61+
62+
env.applyConfig(false, false);
63+
}
64+
65+
@After
66+
public void tearDown() {
67+
env.setProjects(oldProjects);
68+
env.setGroups(oldGroups);
69+
env.setPluginStack(oldPluginStack);
70+
}
71+
72+
@Test
73+
public void testSingleProject() {
74+
final HttpServletRequest request = createRequest(new String[]{"project-1"}, null);
75+
76+
final PageConfig cfg = PageConfig.get(request);
77+
Assert.assertEquals(new HashSet<>(Arrays.asList("project-1")), cfg.getRequestedProjects());
78+
}
79+
80+
@Test
81+
public void testMultipleProject() {
82+
final HttpServletRequest request = createRequest(new String[]{"project-1", "project-3", "project-6"}, null);
83+
84+
final PageConfig cfg = PageConfig.get(request);
85+
Assert.assertEquals(new HashSet<>(Arrays.asList("project-1", "project-3", "project-6")), cfg.getRequestedProjects());
86+
}
87+
88+
@Test
89+
public void testSingleGroup1() {
90+
final HttpServletRequest request = createRequest(null, new String[]{"group-1-2-3"});
91+
92+
final PageConfig cfg = PageConfig.get(request);
93+
Assert.assertEquals(new HashSet<>(Arrays.asList("project-1", "project-2", "project-3")), cfg.getRequestedProjects());
94+
}
95+
96+
@Test
97+
public void testSingleGroup2() {
98+
final HttpServletRequest request = createRequest(null, new String[]{"group-7-8-9"});
99+
100+
final PageConfig cfg = PageConfig.get(request);
101+
Assert.assertEquals(new HashSet<>(Arrays.asList("project-7", "project-8", "project-9")), cfg.getRequestedProjects());
102+
}
103+
104+
@Test
105+
public void testMultipleGroup() {
106+
final HttpServletRequest request = createRequest(null, new String[]{"group-1-2-3", "group-7-8-9"});
107+
108+
final PageConfig cfg = PageConfig.get(request);
109+
Assert.assertEquals(new HashSet<>(Arrays.asList(
110+
"project-1", "project-2", "project-3",
111+
"project-7", "project-8", "project-9")), cfg.getRequestedProjects());
112+
}
113+
114+
@Test
115+
public void testMixedGroupAndProjectAddingNewProjects() {
116+
final HttpServletRequest request = createRequest(new String[]{"project-1", "project-6"}, new String[]{"group-7-8-9"});
117+
118+
final PageConfig cfg = PageConfig.get(request);
119+
Assert.assertEquals(new HashSet<>(Arrays.asList(
120+
"project-1", "project-6",
121+
"project-7", "project-8", "project-9")), cfg.getRequestedProjects());
122+
}
123+
124+
125+
@Test
126+
public void testMixedGroupNonExistentGroupAndProjectAddingNewProjects() {
127+
final HttpServletRequest request = createRequest(new String[]{"project-1", "project-6"}, new String[]{"no-group", "group-7-8-9"});
128+
129+
final PageConfig cfg = PageConfig.get(request);
130+
Assert.assertEquals(new HashSet<>(Arrays.asList(
131+
"project-1", "project-6",
132+
"project-7", "project-8", "project-9")), cfg.getRequestedProjects());
133+
}
134+
135+
@Test
136+
public void testMixedGroupAndProjectInclusion() {
137+
final HttpServletRequest request = createRequest(new String[]{"project-1", "project-2"}, new String[]{"group-1-2-3", "group-7-8-9"});
138+
139+
final PageConfig cfg = PageConfig.get(request);
140+
Assert.assertEquals(new HashSet<>(Arrays.asList(
141+
"project-1", "project-2", "project-3",
142+
"project-7", "project-8", "project-9")), cfg.getRequestedProjects());
143+
}
144+
145+
/**
146+
* Assumes that there is no defaultProjects and no cookie set up.
147+
*/
148+
@Test
149+
public void testNonExistentProject() {
150+
final HttpServletRequest request = createRequest(null, new String[]{"no-project"});
151+
152+
final PageConfig cfg = PageConfig.get(request);
153+
Assert.assertEquals(new HashSet<>(), cfg.getRequestedProjects());
154+
}
155+
156+
/**
157+
* Assumes that there is no defaultProjects and no cookie set up.
158+
*/
159+
@Test
160+
public void testNonExistentGroup() {
161+
final HttpServletRequest request = createRequest(null, new String[]{"no-group"});
162+
163+
final PageConfig cfg = PageConfig.get(request);
164+
Assert.assertEquals(new HashSet<>(), cfg.getRequestedProjects());
165+
}
166+
167+
/**
168+
* Create a request with the specified path elements.
169+
*
170+
* @return a servlet request for the specified path
171+
*/
172+
private static HttpServletRequest createRequest(
173+
final String[] projects,
174+
final String[] groups) {
175+
final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
176+
Mockito.when(request.getParameterValues(PageConfig.PROJECT_PARAM_NAME)).thenReturn(projects);
177+
Mockito.when(request.getParameterValues(PageConfig.GROUP_PARAM_NAME)).thenReturn(groups);
178+
return request;
179+
}
180+
}

0 commit comments

Comments
 (0)