Skip to content

Commit d217704

Browse files
Merge 26.3 to develop
2 parents 1d43f05 + e54eed7 commit d217704

2 files changed

Lines changed: 68 additions & 54 deletions

File tree

LDK/src/org/labkey/ldk/LDKController.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
import java.util.Map;
9393
import java.util.Set;
9494
import java.util.function.Predicate;
95+
import java.util.stream.Collectors;
9596

9697
public class LDKController extends SpringActionController
9798
{
@@ -439,9 +440,9 @@ public ModelAndView getView(Object form, BindException errors) throws Exception
439440
List<String> messages = service.validateContainerScopedTables(false);
440441

441442
String sb = "This page is designed to inspect all registered container scoped tables and report any tables with duplicate keys in the same container. This should be enforced by the user schema; however, direct DB inserts will bypass this check.<p>" +
442-
StringUtils.join(messages, "<br>");
443+
messages.stream().map(PageFlowUtil::filter).collect(Collectors.joining("<br>"));
443444

444-
return new HtmlView(HtmlString.of(sb));
445+
return new HtmlView(HtmlString.unsafe(sb));
445446
}
446447

447448
@Override
@@ -912,7 +913,7 @@ public ModelAndView getView(Object form, BindException errors) throws Exception
912913
}
913914
catch (URISyntaxException e)
914915
{
915-
return new HtmlView(HtmlString.unsafe("Invalid redirect URL set: " + urlString));
916+
return new HtmlView(HtmlString.of("Invalid redirect URL set: " + urlString));
916917
}
917918
}
918919
}

laboratory/src/org/labkey/laboratory/LaboratoryController.java

Lines changed: 64 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
import org.labkey.api.util.ErrorRenderer;
8181
import org.labkey.api.util.ExceptionUtil;
8282
import org.labkey.api.util.FileUtil;
83+
import org.labkey.api.util.HtmlString;
8384
import org.labkey.api.util.JsonUtil;
8485
import org.labkey.api.util.Pair;
8586
import org.labkey.api.util.URLHelper;
@@ -107,6 +108,16 @@
107108
import java.util.Map;
108109
import java.util.Set;
109110

111+
import static org.labkey.api.util.DOM.BR;
112+
import static org.labkey.api.util.DOM.INPUT;
113+
import static org.labkey.api.util.DOM.P;
114+
import static org.labkey.api.util.DOM.TABLE;
115+
import static org.labkey.api.util.DOM.TD;
116+
import static org.labkey.api.util.DOM.TR;
117+
import static org.labkey.api.util.DOM.at;
118+
import static org.labkey.api.util.DOM.createHtmlFragment;
119+
import static org.labkey.api.util.DOM.Attribute.style;
120+
110121

111122
public class LaboratoryController extends SpringActionController
112123
{
@@ -127,13 +138,13 @@ public ModelAndView getView(PlanExptRunForm form, BindException errors) throws E
127138
Integer assayId = form.getAssayId();
128139
if (assayId == null)
129140
{
130-
return new HtmlView("Error: must provide a rowId for the assay");
141+
return new HtmlView(HtmlString.of("Error: must provide a rowId for the assay"));
131142
}
132143

133144
AssayDataProvider ad = LaboratoryService.get().getDataProviderForAssay(assayId);
134145
if (ad == null || !ad.supportsRunTemplates())
135146
{
136-
return new HtmlView("Error: this assay does not support requests");
147+
return new HtmlView(HtmlString.of("Error: this assay does not support requests"));
137148
}
138149

139150
Module labModule = ModuleLoader.getInstance().getModule(LaboratoryModule.NAME);
@@ -173,15 +184,13 @@ public void validateCommand(Object form, Errors errors)
173184
@Override
174185
public ModelAndView getConfirmView(Object form, BindException errors) throws Exception
175186
{
176-
StringBuilder msg = new StringBuilder();
177-
msg.append("Certain assays can have performance improved by the addition of indexes, which can be suggested by modules. The following indexes are recommended for the assays installed on this server:<p>");
178-
179187
List<String> msgs = LaboratoryManager.get().createIndexes(getUser(), false, false);
180-
msg.append(StringUtils.join(msgs, "<br>"));
181188

182-
msg.append("<p>Do you want to continue?");
183-
184-
return new HtmlView(msg.toString());
189+
return new HtmlView(createHtmlFragment(
190+
"Certain assays can have performance improved by the addition of indexes, which can be suggested by modules. The following indexes are recommended for the assays installed on this server:",
191+
P(msgs.stream().map(msg -> createHtmlFragment(msg, BR()))),
192+
P("Do you want to continue?")
193+
));
185194
}
186195

187196
@Override
@@ -232,17 +241,12 @@ public ModelAndView getConfirmView(EnsureAssayFieldsForm form, BindException err
232241
{
233242
try
234243
{
235-
StringBuilder sb = new StringBuilder();
236-
sb.append("This action will iterate all protocols for the assay " + form.getProviderName() + " and append any columns present in the definition, but lacking from that instance of the assay. The following changes will be made:<br><br>");
237244
List<String> messages = AssayHelper.ensureAssayFields(getUser(), form.getProviderName(), form.isRenameConflicts(), true);
238-
for (String msg : messages)
239-
{
240-
sb.append(msg).append("<br><br>");
241-
}
242-
243-
sb.append("<br>Do you want to continue?");
244-
245-
return new HtmlView(sb.toString());
245+
return new HtmlView(createHtmlFragment(
246+
"This action will iterate all protocols for the assay " + form.getProviderName() + " and append any columns present in the definition, but lacking from that instance of the assay. The following changes will be made:", BR(), BR(),
247+
messages.stream().map(msg -> createHtmlFragment(msg, BR(), BR())),
248+
BR(), "Do you want to continue?"
249+
));
246250
}
247251
catch (ChangePropertyDescriptorException e)
248252
{
@@ -308,25 +312,23 @@ public void validateCommand(SetTableIncrementForm form, Errors errors)
308312
@Override
309313
public ModelAndView getConfirmView(SetTableIncrementForm form, BindException errors) throws Exception
310314
{
311-
StringBuilder sb = new StringBuilder();
312-
sb.append("This allows you to reset the current value for an auto-incrementing table<br><br>");
313-
sb.append("<table style='border-collapse: collapse;'>");
314-
315315
String schema = form.getSchemaName() == null ? "" : form.getSchemaName();
316-
sb.append("<tr><td>Schema:</td><td><input name=\"schema\" value=\"" + schema + "\"></td></tr>");
317-
318316
String query = form.getQueryName() == null ? "" : form.getQueryName();
319-
sb.append("<tr><td>Query:</td><td><input name=\"query\" value=\"" + query + "\"></td></tr>");
320317

321318
ContainerIncrementingTable ti = getTable(schema, query, errors, false);
322-
Integer value = null;
319+
Integer currentId = null;
323320
if (ti != null)
324-
value = ti.getCurrentId(getContainer());
325-
326-
sb.append("<tr><td>Value:</td><td><input name=\"value\" value=\"" + (value == null ? "" : value) + "\"></td></tr>");
327-
sb.append("</table><br>Do you want to continue?");
321+
currentId = ti.getCurrentId(getContainer());
328322

329-
return new HtmlView(sb.toString());
323+
return new HtmlView(createHtmlFragment(
324+
"This allows you to reset the current value for an auto-incrementing table", BR(), BR(),
325+
TABLE(at(style, "border-collapse: collapse;"),
326+
TR(TD("Schema:"), TD(INPUT(at().name("schema").value(schema)))),
327+
TR(TD("Query:"), TD(INPUT(at().name("query").value(query)))),
328+
TR(TD("Value:"), TD(INPUT(at().name("value").value(currentId == null ? "" : currentId.toString()))))
329+
),
330+
BR(), "Do you want to continue?"
331+
));
330332
}
331333

332334
@Override
@@ -468,7 +470,7 @@ public void validateCommand(Object form, Errors errors)
468470
@Override
469471
public ModelAndView getConfirmView(Object form, BindException errors) throws Exception
470472
{
471-
return new HtmlView("This action will iterate all workbooks in the current folder and create laboratory experiments for them as needed");
473+
return new HtmlView(HtmlString.of("This action will iterate all workbooks in the current folder and create laboratory experiments for them as needed"));
472474
}
473475

474476
@Override
@@ -507,20 +509,18 @@ public void validateCommand(SetTableIncrementForm form, Errors errors)
507509
@Override
508510
public ModelAndView getConfirmView(SetTableIncrementForm form, BindException errors) throws Exception
509511
{
510-
StringBuilder sb = new StringBuilder();
511-
sb.append("This allows you to initialize the autoincrementing column for the provided schema/query<br><br>");
512-
sb.append("This is very rarely required and was created as a helper for admins with a good deal of knowledge about this module. Under most cases these columns will be automatically populated and you will not need to worry about this. If you are unsure about this page, please post on the LabKey help forums, which are read by the authors of this module.<br><br>");
513-
sb.append("<table style='border-collapse: collapse;'>");
514-
515512
String schema = form.getSchemaName() == null ? "" : form.getSchemaName();
516-
sb.append("<tr><td>Schema:</td><td><input name=\"schema\" value=\"" + schema + "\"></td></tr>");
517-
518513
String query = form.getQueryName() == null ? "" : form.getQueryName();
519-
sb.append("<tr><td>Query:</td><td><input name=\"query\" value=\"" + query + "\"></td></tr>");
520514

521-
sb.append("</table><br>Do you want to continue?");
522-
523-
return new HtmlView(sb.toString());
515+
return new HtmlView(createHtmlFragment(
516+
"This allows you to initialize the autoincrementing column for the provided schema/query", BR(), BR(),
517+
"This is very rarely required and was created as a helper for admins with a good deal of knowledge about this module. Under most cases these columns will be automatically populated and you will not need to worry about this. If you are unsure about this page, please post on the LabKey help forums, which are read by the authors of this module.", BR(), BR(),
518+
TABLE(at(style, "border-collapse: collapse;"),
519+
TR(TD("Schema:"), TD(INPUT(at().name("schema").value(schema)))),
520+
TR(TD("Query:"), TD(INPUT(at().name("query").value(query))))
521+
),
522+
BR(), "Do you want to continue?"
523+
));
524524
}
525525

526526

@@ -579,7 +579,8 @@ public void validateCommand(Object form, Errors errors)
579579
@Override
580580
public ModelAndView getConfirmView(Object form, BindException errors) throws Exception
581581
{
582-
return new HtmlView("This action will reset webparts and tabs for the current folder and all children to the default Laboratory FolderType, if these folders are either Laboratory Folders or Expt Workbooks");
582+
HtmlString message = HtmlString.of("This action will reset webparts and tabs for the current folder and all children to the default Laboratory FolderType, if these folders are either Laboratory Folders or Expt Workbooks");
583+
return new HtmlView(message);
583584
}
584585

585586
@Override
@@ -647,8 +648,9 @@ public String getResponse(ProcessAssayForm form, Map<String, Pair<FileLike, Stri
647648
throw new UploadException("No Assay Id Provided", HttpServletResponse.SC_BAD_REQUEST);
648649
}
649650

651+
// getExpProtocol() is unscoped, so verify the protocol is in scope for this container before using it.
650652
ExpProtocol protocol = ExperimentService.get().getExpProtocol(form.getLabkeyAssayId());
651-
if (protocol == null)
653+
if (protocol == null || !AssayService.get().getAssayProtocols(getContainer()).contains(protocol))
652654
{
653655
throw new UploadException("Unable to find assay protocol with Id: " + form.getLabkeyAssayId(), HttpServletResponse.SC_BAD_REQUEST);
654656
}
@@ -936,8 +938,9 @@ public ApiResponse execute(SaveTemplateForm form, BindException errors) throws E
936938
{
937939
JSONObject json = new JSONObject(form.getJson());
938940

941+
// getExpProtocol() is unscoped, so verify the protocol is in scope for this container before saving a template against it.
939942
ExpProtocol protocol = ExperimentService.get().getExpProtocol(form.getProtocolId());
940-
if (protocol == null)
943+
if (protocol == null || !AssayService.get().getAssayProtocols(getContainer()).contains(protocol))
941944
{
942945
errors.reject(ERROR_MSG, "Unknown assay: " + form.getProtocolId());
943946
return null;
@@ -1063,8 +1066,9 @@ public void export(ProcessAssayForm form, HttpServletResponse response, BindExce
10631066
return;
10641067
}
10651068

1069+
// getExpProtocol() is unscoped, so verify the protocol is in scope for this container before generating a template against it.
10661070
ExpProtocol protocol = ExperimentService.get().getExpProtocol(form.getLabkeyAssayId());
1067-
if (protocol == null)
1071+
if (protocol == null || !AssayService.get().getAssayProtocols(getContainer()).contains(protocol))
10681072
{
10691073
throw new AbstractFileUploadAction.UploadException("Unable to find assay protocol with Id: " + form.getLabkeyAssayId(), HttpServletResponse.SC_BAD_REQUEST);
10701074
}
@@ -1514,8 +1518,9 @@ public ApiResponse execute(AssayImportHeadersForm form, BindException errors)
15141518
return new ApiSimpleResponse(results);
15151519
}
15161520

1521+
// getExpProtocol() is unscoped, so verify the protocol is in scope for this container before returning its import columns.
15171522
ExpProtocol protocol = ExperimentService.get().getExpProtocol(form.getProtocol());
1518-
if (protocol == null)
1523+
if (protocol == null || !AssayService.get().getAssayProtocols(getContainer()).contains(protocol))
15191524
{
15201525
errors.reject(ERROR_MSG, "Protocol not found: " + form.getProtocol());
15211526
return new ApiSimpleResponse(results);
@@ -1916,8 +1921,16 @@ public ApiResponse execute(ImportMethodsForm form, BindException errors)
19161921
List<ExpProtocol> protocols = new ArrayList<>();
19171922
if (form.getAssayId() != null)
19181923
{
1919-
protocols.add(ExperimentService.get().getExpProtocol(form.getAssayId()));
1920-
ap = AssayService.get().getProvider(protocols.get(0));
1924+
ExpProtocol protocol = ExperimentService.get().getExpProtocol(form.getAssayId());
1925+
// getExpProtocol() is unscoped, so verify the protocol is in scope before echoing its metadata; otherwise a user
1926+
// could enumerate arbitrary row ids and harvest assay names and container paths from folders they cannot read.
1927+
if (protocol == null || !AssayService.get().getAssayProtocols(getContainer()).contains(protocol))
1928+
{
1929+
errors.reject(ERROR_MSG, "Unknown assay: " + form.getAssayId());
1930+
return null;
1931+
}
1932+
protocols.add(protocol);
1933+
ap = AssayService.get().getProvider(protocol);
19211934
}
19221935
else if (form.getAssayType() != null)
19231936
{

0 commit comments

Comments
 (0)