Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.json.JSONArray;
import org.json.JSONObject;
import org.labkey.api.assay.AssayProvider;
import org.labkey.api.assay.AssayService;
import org.labkey.api.collections.CaseInsensitiveHashMap;
import org.labkey.api.data.Container;
import org.labkey.api.data.ContainerManager;
import org.labkey.api.data.ContainerType;
import org.labkey.api.data.ConvertHelper;
import org.labkey.api.data.DbSchema;
import org.labkey.api.data.RuntimeSQLException;
import org.labkey.api.data.SimpleFilter;
import org.labkey.api.data.Table;
import org.labkey.api.data.TableInfo;
import org.labkey.api.data.TableSelector;
import org.labkey.api.exp.PropertyDescriptor;
Expand All @@ -44,14 +45,14 @@
import org.labkey.api.laboratory.LaboratoryService;
import org.labkey.api.query.BatchValidationException;
import org.labkey.api.query.FieldKey;
import org.labkey.api.query.QueryService;
import org.labkey.api.query.UserSchema;
import org.labkey.api.query.ValidationException;
import org.labkey.api.reader.ColumnDescriptor;
import org.labkey.api.reader.ExcelFactory;
import org.labkey.api.reader.Readers;
import org.labkey.api.reader.TabLoader;
import org.labkey.api.security.User;
import org.labkey.api.assay.AssayProvider;
import org.labkey.api.assay.AssayService;
import org.labkey.api.util.FileType;
import org.labkey.api.util.JsonUtil;
import org.labkey.api.util.Pair;
Expand Down Expand Up @@ -466,10 +467,16 @@ protected void saveTemplate(ViewContext ctx, int templateId, int runId) throws B
{
try
{
//validate the template exists
TableInfo ti = DbSchema.get("laboratory").getTable("assay_run_templates");
//validate the template exists. Note: this should always act against the current container, even if the container is a workbook (e.g., it should not allow cross-workbook actions)
UserSchema us = QueryService.get().getUserSchema(ctx.getUser(), ctx.getContainer(), "laboratory");
if (us == null)
{
throw new IllegalStateException("The laboratory schema is not available in container: " + ctx.getContainer().getPath());
}

TableInfo ti = us.getTable("assay_run_templates");
TableSelector ts = new TableSelector(ti, new SimpleFilter(FieldKey.fromString("rowid"), templateId), null);
if (ts.getRowCount() == 0)
if (!ts.exists())
{
throw new BatchValidationException(Collections.singletonList(new ValidationException("Unknown template: " + templateId)), null);
}
Expand All @@ -478,11 +485,11 @@ protected void saveTemplate(ViewContext ctx, int templateId, int runId) throws B
row.put("runid", runId);
row.put("status", "Complete");

Table.update(ctx.getUser(), ti, row, templateId);
ti.getUpdateService().updateRows(ctx.getUser(), ctx.getContainer(), Arrays.asList(row), Arrays.asList(Map.of("rowId", templateId)), null, null);
Comment thread
bbimber marked this conversation as resolved.
}
catch (RuntimeSQLException e)
catch (Exception e)
{
throw new BatchValidationException(Collections.singletonList(new ValidationException(e.getSQLException().getMessage())), null);
throw new BatchValidationException(Collections.singletonList(new ValidationException(e.getMessage())), null);
}
}

Expand Down Expand Up @@ -584,8 +591,12 @@ protected Map<String, Map<String, Object>> getTemplateRowMap(ImportContext conte
if (templateId == null)
return ret;

TableInfo ti = DbSchema.get("laboratory").getTable("assay_run_templates");

UserSchema us = QueryService.get().getUserSchema(context.getViewContext().getUser(), context.getViewContext().getContainer().getContainerFor(ContainerType.DataType.tabParent), "laboratory");
Comment thread
bbimber marked this conversation as resolved.
if (us == null)
{
throw new IllegalStateException("Could not find the laboratory schema in container: " + context.getViewContext().getContainer().getContainerFor(ContainerType.DataType.tabParent).getPath());
}
TableInfo ti = us.getTable("assay_run_templates");
TableSelector ts = new TableSelector(ti, new SimpleFilter(FieldKey.fromString("rowid"), templateId), null);
Map<String, Object>[] maps = ts.getMapArray();
if (maps.length == 0)
Expand All @@ -595,6 +606,18 @@ protected Map<String, Map<String, Object>> getTemplateRowMap(ImportContext conte

Map<String, Object> map = maps[0];
JSONObject templateJson = new JSONObject((String)map.get("json"));

// This enforces that the request and existing record are from the same container, including for workbook/parents:
Container rowContainer = ContainerManager.getForId(String.valueOf(map.get("container")));
if (rowContainer == null)
{
throw new IllegalStateException("Unable to determine the container for template: " + templateId);
}
else if (!rowContainer.equals(context.getViewContext().getContainer()))
{
throw new IllegalStateException("Template is from the wrong container: " + templateId);
}

JSONArray rows = templateJson.getJSONArray("ResultRows");
for (JSONObject row : JsonUtil.toJSONObjectList(rows))
{
Expand Down
80 changes: 70 additions & 10 deletions laboratory/src/org/labkey/laboratory/assay/AssayHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
import org.labkey.api.collections.CollectionUtils;
import org.labkey.api.data.Container;
import org.labkey.api.data.ContainerManager;
import org.labkey.api.data.RuntimeSQLException;
import org.labkey.api.data.ContainerType;
import org.labkey.api.data.SimpleFilter;
import org.labkey.api.data.TSVMapWriter;
import org.labkey.api.data.Table;
import org.labkey.api.data.TableInfo;
import org.labkey.api.data.TableSelector;
import org.labkey.api.exp.ChangePropertyDescriptorException;
Expand All @@ -51,9 +51,14 @@
import org.labkey.api.laboratory.assay.AssayDataProvider;
import org.labkey.api.laboratory.assay.AssayImportMethod;
import org.labkey.api.query.BatchValidationException;
import org.labkey.api.query.FieldKey;
import org.labkey.api.query.QueryService;
import org.labkey.api.query.UserSchema;
import org.labkey.api.query.ValidationException;
import org.labkey.api.security.User;
import org.labkey.api.security.permissions.UpdatePermission;
import org.labkey.api.util.FileUtil;
import org.labkey.api.util.PageFlowUtil;
import org.labkey.api.util.Pair;
import org.labkey.api.view.ActionURL;
import org.labkey.api.view.ViewContext;
Expand All @@ -66,6 +71,7 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -125,35 +131,46 @@ public Map<String, Object> saveTemplate(User u, Container c, ExpProtocol protoco
{
validateTemplate(u, c, protocol, templateId, title, importMethod, json);

TableInfo ti = LaboratorySchema.getInstance().getSchema().getTable(LaboratorySchema.TABLE_ASSAY_RUN_TEMPLATES);
UserSchema us = QueryService.get().getUserSchema(u, c, "laboratory");
if (us == null)
{
throw new IllegalStateException("Could not find the laboratory schema in container: " + c.getPath());
}

TableInfo ti = us.getTable(LaboratorySchema.TABLE_ASSAY_RUN_TEMPLATES);
Map<String, Object> row = new HashMap<>();
row.put("assayId", protocol.getRowId());
row.put("title", title);
row.put("importMethod", importMethod);
row.put("json", json.toString());
row.put("container", c.getId());

if (templateId == null)
{
row = Table.insert(u, ti, row);
BatchValidationException bve = new BatchValidationException();
List<Map<String, Object>> rows = ti.getUpdateService().insertRows(u, c, Arrays.asList(row), bve, null, null);
if (bve.hasErrors())
{
throw bve;
}

return rows.get(0);
}
else
{
row.put("rowid", templateId);
row = Table.update(u, ti, row, templateId);
List<Map<String, Object>> rows = ti.getUpdateService().updateRows(u, c, Arrays.asList(row), Arrays.asList(Map.of("rowId", templateId)), null, null);
return rows.get(0);
}

return row;
}
catch (RuntimeSQLException e)
catch (Exception e)
{
_log.error(e.getMessage(), e);
errors.addRowError(new ValidationException(e.getMessage()));
throw errors;
}
}

public void validateTemplate(User u, Container c, ExpProtocol protocol, Integer templateId, String title, String importMethod, JSONObject json) throws BatchValidationException
public void validateTemplate(User u, Container c, ExpProtocol protocol, @Nullable Integer templateId, String title, String importMethod, JSONObject json) throws BatchValidationException
{
BatchValidationException errors = new BatchValidationException();

Expand All @@ -178,6 +195,49 @@ public void validateTemplate(User u, Container c, ExpProtocol protocol, Integer
throw errors;
}

// Verify if this template exists and permissions. This expects any existing row to be present in the current container:
if (templateId != null)
{
// This queries the current container+workbooks to identify the existence of rows in other reasonable containers:
UserSchema us = QueryService.get().getUserSchema(u, c.getContainerFor(ContainerType.DataType.tabParent), "laboratory");
Comment thread
bbimber marked this conversation as resolved.
TableInfo ti = us.getTable("assay_run_templates");
TableSelector ts = new TableSelector(ti, PageFlowUtil.set("container"), new SimpleFilter(FieldKey.fromString("rowId"), templateId), null);
if (ts.exists())
{
Container rowContainer = ContainerManager.getForId(ts.getObject(String.class));
if (rowContainer == null)
{
errors.addRowError(new ValidationException("Unable to determine the container for template: " + templateId));
throw errors;
}

if (!rowContainer.hasPermission("AssayHelper.validateTemplate()", u, UpdatePermission.class))
{
errors.addRowError(new ValidationException("The current user does not have permission to edit template: " + templateId));
throw errors;
}

if (!c.equals(rowContainer))
{
errors.addRowError(new ValidationException("Template " + templateId + " is not from this folder"));
throw errors;
}
}
else
{
errors.addRowError(new ValidationException("Unable to find template with ID: " + templateId));
throw errors;
}
}
else
{
if (!c.hasPermission("AssayHelper.validateTemplate()", u, UpdatePermission.class))
{
errors.addRowError(new ValidationException("The current user does not have permission to creates templates in folder: " + c.getName()));
throw errors;
}
}

method.validateTemplate(u, c, protocol, templateId, title, json, errors);

if (errors.hasErrors())
Expand Down