From adcd90dc58b0e6e2193b0e364b25c990aaeb775e Mon Sep 17 00:00:00 2001 From: Cory Nathe Date: Thu, 14 Mar 2019 15:10:18 +0000 Subject: [PATCH 1/9] Secure Issue 36967: SQL Injection in LabKey SQL via LeveyJennings report (Luminex) --- .../org/labkey/luminex/view/leveyJenningsReport.jsp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/luminex/src/org/labkey/luminex/view/leveyJenningsReport.jsp b/luminex/src/org/labkey/luminex/view/leveyJenningsReport.jsp index 3e0062b1b7..fda77543f6 100644 --- a/luminex/src/org/labkey/luminex/view/leveyJenningsReport.jsp +++ b/luminex/src/org/labkey/luminex/view/leveyJenningsReport.jsp @@ -133,18 +133,19 @@ // verify that the given titration/singlepointcontrol exists and has run's associated with it as a Standard or QC Control var sql; - if ('Titration' == _controlType) { - sql = "SELECT COUNT(*) AS RunCount FROM Titration WHERE Name='" + _controlName + "' AND IncludeInQcReport=true"; + if ('Titration' === _controlType) { + sql = "SELECT COUNT(*) AS RunCount FROM Titration WHERE Name=CONTROL_NAME AND IncludeInQcReport=true"; } else { - sql = "SELECT COUNT(*) AS RunCount FROM SinglePointControl WHERE Name='" + _controlName + "'"; + sql = "SELECT COUNT(*) AS RunCount FROM SinglePointControl WHERE Name=CONTROL_NAME"; } LABKEY.Query.executeSql({ containerFilter: LABKEY.Query.containerFilter.allFolders, schemaName: 'assay.Luminex.' + LABKEY.QueryKey.encodePart(_protocolName), - sql: sql, + sql: 'PARAMETERS(CONTROL_NAME VARCHAR) ' + sql, + parameters: {CONTROL_NAME: _controlName}, success: function(data) { - if (data.rows.length == 0 || data.rows[0]['RunCount'] == 0) + if (data.rows.length === 0 || data.rows[0]['RunCount'] === 0) { Ext.get('graphParamsPanel').update("Error: there were no records found in '" + $h(_protocolName) + "' for '" + $h(_controlName) + "'."); From f67ab6a108868cd6c68229ccc8d8467fa76b57fa Mon Sep 17 00:00:00 2001 From: Matthew Bellew Date: Thu, 14 Mar 2019 23:26:01 +0000 Subject: [PATCH 2/9] Sampleset delete perf -- ExpressionMatrixExperimentListener.beforeMaterialDelete() -- ExperimentServiceImpl.deleteRunsUsingInputs() --- .../ExpressionMatrixExperimentListener.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/microarray/src/org/labkey/microarray/matrix/ExpressionMatrixExperimentListener.java b/microarray/src/org/labkey/microarray/matrix/ExpressionMatrixExperimentListener.java index 1563287297..53925e2bcf 100644 --- a/microarray/src/org/labkey/microarray/matrix/ExpressionMatrixExperimentListener.java +++ b/microarray/src/org/labkey/microarray/matrix/ExpressionMatrixExperimentListener.java @@ -18,12 +18,16 @@ import org.labkey.api.data.Container; import org.labkey.api.data.SQLFragment; import org.labkey.api.data.SqlExecutor; +import org.labkey.api.data.dialect.SqlDialect; import org.labkey.api.exp.api.ExpMaterial; +import org.labkey.api.exp.api.ExpObject; import org.labkey.api.exp.api.ExperimentListener; import org.labkey.api.security.User; import org.labkey.microarray.query.MicroarrayUserSchema; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * User: jeckels @@ -34,14 +38,12 @@ public class ExpressionMatrixExperimentListener implements ExperimentListener @Override public void beforeMaterialDelete(List materials, Container container, User user) { + SqlDialect d = MicroarrayUserSchema.getSchema().getSqlDialect(); SqlExecutor sqlExecutor = new SqlExecutor(MicroarrayUserSchema.getSchema()); - for (ExpMaterial material : materials) - { - SQLFragment sql = new SQLFragment("DELETE FROM "); - sql.append(MicroarrayUserSchema.getSchema().getTable("FeatureData")); - sql.append(" WHERE SampleId = ?"); - sql.add(material.getRowId()); - sqlExecutor.execute(sql); - } + SQLFragment sql = new SQLFragment("DELETE FROM "); + sql.append(MicroarrayUserSchema.getSchema().getTable("FeatureData")); + sql.append(" WHERE SampleId "); + d.appendInClauseSql(sql, materials.stream().map(ExpObject::getRowId).collect(Collectors.toList())); + sqlExecutor.execute(sql); } } From 6b7b5d568300093a78d9d1a69c6cb035444dc9ea Mon Sep 17 00:00:00 2001 From: Susan Hert Date: Wed, 20 Mar 2019 19:01:11 +0000 Subject: [PATCH 3/9] Use new parameterized method for getting paths to platform modules and commonAssay modules in anticipation of migration to Git. --- flow/build.gradle | 8 ++++---- ms1/build.gradle | 4 ++-- ms2/build.gradle | 7 +++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/flow/build.gradle b/flow/build.gradle index 76efb635ab..7c6f214a35 100644 --- a/flow/build.gradle +++ b/flow/build.gradle @@ -9,9 +9,9 @@ sourceSets { } dependencies { - BuildUtils.addLabKeyDependency(project: project, config: "engineCompile", depProjectPath: ":server:modules:flow", depProjectConfig: 'xmlSchema') - BuildUtils.addLabKeyDependency(project: project, config: "engineCompile", depProjectPath: ":server:api") - BuildUtils.addLabKeyDependency(project: project, config: "engineCompile", depProjectPath: ":server:internal") + BuildUtils.addLabKeyDependency(project: project, config: "engineCompile", depProjectPath: project.path, depProjectConfig: 'xmlSchema') + BuildUtils.addLabKeyDependency(project: project, config: "engineCompile", depProjectPath: BuildUtils.getApiProjectPath(project.gradle)) + BuildUtils.addLabKeyDependency(project: project, config: "engineCompile", depProjectPath: BuildUtils.getInternalProjectPath(project.gradle)) engineCompile "org.labkey:labkey-client-api:${project.version}" engineCompile 'org.apache.tomcat:jsp-api' engineCompile 'org.apache.tomcat:jasper' @@ -19,7 +19,7 @@ dependencies { compile sourceSets.engine.output jspCompile sourceSets.engine.output - BuildUtils.addLabKeyDependency(project: project, config: "jspCompile", depProjectPath: ":server:modules:flow", depProjectConfig: 'xmlSchema') + BuildUtils.addLabKeyDependency(project: project, config: "jspCompile", depProjectPath: project.path, depProjectConfig: 'xmlSchema') } project.task("engineJar", diff --git a/ms1/build.gradle b/ms1/build.gradle index cf161e106c..e35dafffa3 100644 --- a/ms1/build.gradle +++ b/ms1/build.gradle @@ -1,8 +1,8 @@ import org.labkey.gradle.util.BuildUtils dependencies { - BuildUtils.addLabKeyDependency(project: project, config: "compile", depProjectPath: ":server:modules:ms2", depProjectConfig: 'apiCompile', specialParams: { - if(!BuildUtils.shouldBuildFromSource(project.project(":server:modules:ms2"))) { + BuildUtils.addLabKeyDependency(project: project, config: "compile", depProjectPath: BuildUtils.getCommonAssayModuleProjectPath(project.gradle, "ms2"), depProjectConfig: 'apiCompile', specialParams: { + if(!BuildUtils.shouldBuildFromSource(project.project( BuildUtils.getCommonAssayModuleProjectPath(project.gradle, "ms2")))) { exclude group: 'org.labkey', module: 'ms1' } }) diff --git a/ms2/build.gradle b/ms2/build.gradle index d7f7367ffb..4826d4ed4e 100644 --- a/ms2/build.gradle +++ b/ms2/build.gradle @@ -1,10 +1,9 @@ import org.labkey.gradle.util.BuildUtils -dependencies -{ +dependencies { external 'commons-httpclient:commons-httpclient:3.1' - BuildUtils.addLabKeyDependency(project: project, config: "compile", depProjectPath: ":server:modules:ms1", depProjectConfig: 'apiCompile', specialParams: { - if(!BuildUtils.shouldBuildFromSource(project.project(":server:modules:ms1"))) { + BuildUtils.addLabKeyDependency(project: project, config: "compile", depProjectPath: BuildUtils.getCommonAssayModuleProjectPath(project.gradle, "ms1"), depProjectConfig: 'apiCompile', specialParams: { + if(!BuildUtils.shouldBuildFromSource(project.project(BuildUtils.getCommonAssayModuleProjectPath(project.gradle, "ms1")))) { exclude group: 'org.labkey', module: 'ms2' } }) From 72c9bca1a7b6f3d8780954585b2b8cb560f03291 Mon Sep 17 00:00:00 2001 From: Susan Hert Date: Wed, 20 Mar 2019 20:02:48 +0000 Subject: [PATCH 4/9] Don't apply java plugin and labkey Module plugin to internal and api (when the become a subproject here) --- build.gradle | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a3b4c308c6..9953403d8b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,13 @@ +import org.labkey.gradle.util.BuildUtils import org.labkey.gradle.util.ModuleFinder subprojects { Project p -> - if (p.projectDir.exists() && ModuleFinder.isPotentialModule(p)) + if (p.projectDir.exists() && + ModuleFinder.isPotentialModule(p) && + !p.path.equals(BuildUtils.getApiProjectPath(p.gradle)) && + !p.path.equals(BuildUtils.getInternalProjectPath(p.gradle)) + ) { apply plugin: 'java' apply plugin: 'org.labkey.module' From 28e1fce3937a569780213e38945a4689f77990ce Mon Sep 17 00:00:00 2001 From: labkey-tchad Date: Mon, 25 Mar 2019 09:02:04 -0700 Subject: [PATCH 5/9] Fix test file locations for new project layout --- .../org/labkey/test/tests/luminex/LuminexPositivityTest.java | 2 +- .../test/src/org/labkey/test/tests/luminex/LuminexTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/luminex/test/src/org/labkey/test/tests/luminex/LuminexPositivityTest.java b/luminex/test/src/org/labkey/test/tests/luminex/LuminexPositivityTest.java index 98f729867b..a4ed378d6a 100644 --- a/luminex/test/src/org/labkey/test/tests/luminex/LuminexPositivityTest.java +++ b/luminex/test/src/org/labkey/test/tests/luminex/LuminexPositivityTest.java @@ -56,7 +56,7 @@ public final class LuminexPositivityTest extends LuminexTest private Boolean _expectedNegativeControlValue = false; private Boolean _newNegativeControlValue = false; private static String _negControlAnalyte = _analyteNames.get(1); - protected static final File POSITIVITY_RTRANSFORM_SCRIPT_FILE = new File(TestFileUtils.getLabKeyRoot(), "server/modules/luminex/resources/transformscripts/description_parsing_example.pl"); + protected static final File POSITIVITY_RTRANSFORM_SCRIPT_FILE = new File(TestFileUtils.getLabKeyRoot(), "server/modules/commonAssays/luminex/resources/transformscripts/description_parsing_example.pl"); private static final String RUN_ID_BASE = "Positivity"; @BeforeClass diff --git a/luminex/test/src/org/labkey/test/tests/luminex/LuminexTest.java b/luminex/test/src/org/labkey/test/tests/luminex/LuminexTest.java index 717bb44e93..33ac6f45c1 100644 --- a/luminex/test/src/org/labkey/test/tests/luminex/LuminexTest.java +++ b/luminex/test/src/org/labkey/test/tests/luminex/LuminexTest.java @@ -88,8 +88,8 @@ public abstract class LuminexTest extends BaseWebDriverTest public static final File TEST_ASSAY_MULTIPLE_STANDARDS_2 = TestFileUtils.getSampleData("Luminex/plate 2_IgA-Biot (Standard2).xls"); public static final File TEST_ASSAY_MULTIPLE_STANDARDS_3 = TestFileUtils.getSampleData("Luminex/plate 3_IgA-Biot (Standard1).xls"); - public static final File RTRANSFORM_SCRIPT_FILE_LABKEY = new File(TestFileUtils.getLabKeyRoot(), "server/modules/luminex/resources/transformscripts/labkey_luminex_transform.R"); - public static final File RTRANSFORM_SCRIPT_FILE_LAB = new File(TestFileUtils.getLabKeyRoot(), "server/modules/luminex/resources/transformscripts/tomaras_luminex_transform.R"); + public static final File RTRANSFORM_SCRIPT_FILE_LABKEY = new File(TestFileUtils.getLabKeyRoot(), "server/modules/commonAssays/luminex/resources/transformscripts/labkey_luminex_transform.R"); + public static final File RTRANSFORM_SCRIPT_FILE_LAB = new File(TestFileUtils.getLabKeyRoot(), "server/modules/commonAssays/luminex/resources/transformscripts/tomaras_luminex_transform.R"); public static final String ASSAY_ID_FIELD = "name"; public static final String ASSAY_DATA_FILE_LOCATION_MULTIPLE_FIELD = "__primaryFile__"; From d63f0ec1f9d91ebad26978b42fc5e5f094c49d31 Mon Sep 17 00:00:00 2001 From: labkey-dave Date: Mon, 25 Mar 2019 13:32:16 -0700 Subject: [PATCH 6/9] appendNavTrail issues --- ms2/src/org/labkey/ms2/MS2Controller.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ms2/src/org/labkey/ms2/MS2Controller.java b/ms2/src/org/labkey/ms2/MS2Controller.java index ed21541169..9fa29e45eb 100644 --- a/ms2/src/org/labkey/ms2/MS2Controller.java +++ b/ms2/src/org/labkey/ms2/MS2Controller.java @@ -227,10 +227,13 @@ private NavTree appendRunNavTrail(NavTree root, MS2Run run, URLHelper runURL, St { appendRootNavTrail(root, null, page, helpTopic); - if (null != runURL) - root.addChild(run.getDescription(), runURL); - else - root.addChild(run.getDescription()); + if (null != run) + { + if (null != runURL) + root.addChild(run.getDescription(), runURL); + else + root.addChild(run.getDescription()); + } if (null != title) root.addChild(title); From 09e441de4343fa7f915995bc9cad9b81282ec7a9 Mon Sep 17 00:00:00 2001 From: klum Date: Tue, 16 Apr 2019 10:22:06 -0700 Subject: [PATCH 7/9] initial QC state and flag handler interfaces and default implementations --- .../src/org/labkey/luminex/LuminexDataHandler.java | 11 ++++++----- luminex/src/org/labkey/luminex/LuminexModule.java | 6 +++++- nab/src/org/labkey/nab/NabAssayController.java | 7 ++++--- nab/src/org/labkey/nab/NabModule.java | 9 +++++++++ nab/src/org/labkey/nab/query/NabProtocolSchema.java | 12 ------------ 5 files changed, 24 insertions(+), 21 deletions(-) diff --git a/luminex/src/org/labkey/luminex/LuminexDataHandler.java b/luminex/src/org/labkey/luminex/LuminexDataHandler.java index 9d78eb959d..59fec122ed 100644 --- a/luminex/src/org/labkey/luminex/LuminexDataHandler.java +++ b/luminex/src/org/labkey/luminex/LuminexDataHandler.java @@ -684,6 +684,7 @@ private void insertCVQCFlags(User user, ExpRun expRun, List data { LuminexWellGroup wellGroup = analyte.buildWellGroup(dataRows); List allReplicates = wellGroup.getWellData(true); // combine replicates and get mean MFI and %CV + AssayProvider provider = AssayService.get().getProvider(expRun); Set newCVQCFlags = new HashSet<>(); for (LuminexWell replicate : allReplicates) @@ -701,7 +702,7 @@ private void insertCVQCFlags(User user, ExpRun expRun, List data if (!newCVQCFlags.contains(newQcFlag)) { newCVQCFlags.add(newQcFlag); - Table.insert(user, ExperimentService.get().getTinfoAssayQCFlag(), newQcFlag); + AssayService.get().saveFlag(provider, newQcFlag, user); } } } @@ -851,7 +852,7 @@ public static void insertOrUpdateAnalyteSinglePointControlQCFlags(User user, Exp { if (!existingQCFlags.contains(newQCFlag)) { - Table.insert(user, ExperimentService.get().getTinfoAssayQCFlag(), newQCFlag); + AssayService.get().saveFlag(provider, newQCFlag, user); } } @@ -860,7 +861,7 @@ public static void insertOrUpdateAnalyteSinglePointControlQCFlags(User user, Exp { if (!newQCFlags.contains(existingAnalyteTitrationQCFlag)) { - Table.delete(ExperimentService.get().getTinfoAssayQCFlag(), existingAnalyteTitrationQCFlag.getRowId()); + AssayService.get().deleteFlags(provider, existingAnalyteTitrationQCFlag.getRowId(), user); } } } @@ -1520,7 +1521,7 @@ else if (guideSetRow.isAucEnabled() && curveFit.getCurveType().equals("Trapezoid { if (!existingAnalyteTitrationQCFlags.contains(newAnalyteTitrationQCFlag)) { - Table.insert(user, ExperimentService.get().getTinfoAssayQCFlag(), newAnalyteTitrationQCFlag); + AssayService.get().saveFlag(provider, newAnalyteTitrationQCFlag, user); } } @@ -1529,7 +1530,7 @@ else if (guideSetRow.isAucEnabled() && curveFit.getCurveType().equals("Trapezoid { if (!newAnalyteTitrationQCFlags.contains(existingAnalyteTitrationQCFlag)) { - Table.delete(ExperimentService.get().getTinfoAssayQCFlag(), existingAnalyteTitrationQCFlag.getRowId()); + AssayService.get().deleteFlags(provider, existingAnalyteTitrationQCFlag.getRowId(), user); } } } diff --git a/luminex/src/org/labkey/luminex/LuminexModule.java b/luminex/src/org/labkey/luminex/LuminexModule.java index a7599dc05d..2b3d594122 100644 --- a/luminex/src/org/labkey/luminex/LuminexModule.java +++ b/luminex/src/org/labkey/luminex/LuminexModule.java @@ -17,12 +17,14 @@ package org.labkey.luminex; import org.jetbrains.annotations.NotNull; +import org.labkey.api.assay.AssayDefaultFlagHandler; +import org.labkey.api.assay.AssayFlagHandler; +import org.labkey.api.assay.AssayQCFlagColumn; import org.labkey.api.data.Container; import org.labkey.api.exp.api.ExperimentService; import org.labkey.api.exp.property.PropertyService; import org.labkey.api.module.DefaultModule; import org.labkey.api.module.ModuleContext; -import org.labkey.api.study.assay.AssayQCFlagColumn; import org.labkey.api.study.assay.AssayService; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.WebPartFactory; @@ -72,6 +74,8 @@ public void doStartup(ModuleContext moduleContext) AssayService.get().registerAssayProvider(new LuminexAssayProvider()); PropertyService.get().registerDomainKind(new LuminexAnalyteDomainKind()); PropertyService.get().registerDomainKind(new LuminexDataDomainKind()); + + AssayFlagHandler.registerHandler(AssayService.get().getProvider(LuminexAssayProvider.NAME), new AssayDefaultFlagHandler()); } @Override diff --git a/nab/src/org/labkey/nab/NabAssayController.java b/nab/src/org/labkey/nab/NabAssayController.java index 3dc834a349..17b5f98da0 100644 --- a/nab/src/org/labkey/nab/NabAssayController.java +++ b/nab/src/org/labkey/nab/NabAssayController.java @@ -1055,7 +1055,7 @@ public ApiResponse execute(QCControlInfo form, BindException errors) throws Exce DilutionManager.clearWellExclusions(scope.getSqlDialect(), form.getRunId()); // clear out prior qc flags - Table.delete(ExperimentService.get().getTinfoAssayQCFlag(), new SimpleFilter(FieldKey.fromParts("runId"), form.getRunId())); + AssayService.get().deleteFlags(provider, form.getRunId(), getUser()); Set excludedWells = new HashSet<>(); Collection wellRowIds = new HashSet<>(); @@ -1065,7 +1065,7 @@ public ApiResponse execute(QCControlInfo form, BindException errors) throws Exce // add the assay qc flag for the exclusions NabWellQCFlag flag = new NabWellQCFlag(form.getRunId(), well); - Table.insert(getUser(), ExperimentService.get().getTinfoAssayQCFlag(), flag); + AssayService.get().saveFlag(provider, flag, getUser()); } // get the rowid's for the wells to exclude @@ -1257,9 +1257,10 @@ public ApiResponse execute(RenderAssayBean form, BindException errors) { List exclusions = new ArrayList<>(); Map qcFlagMap = new HashMap<>(); + AssayProvider provider = AssayService.get().getProvider(run); // get the saved assay QC flags to pull comment information from - for (NabWellQCFlag flag : new TableSelector(ExperimentService.get().getTinfoAssayQCFlag(), new SimpleFilter(FieldKey.fromParts("runId"), form.getRowId()), null).getArrayList(NabWellQCFlag.class)) + for (NabWellQCFlag flag : AssayService.get().getFlags(provider, form.getRowId(), NabWellQCFlag.class)) { qcFlagMap.put(flag.getKey1(), flag); } diff --git a/nab/src/org/labkey/nab/NabModule.java b/nab/src/org/labkey/nab/NabModule.java index 996c1ffa3d..cb101a7468 100644 --- a/nab/src/org/labkey/nab/NabModule.java +++ b/nab/src/org/labkey/nab/NabModule.java @@ -16,7 +16,9 @@ package org.labkey.nab; import org.jetbrains.annotations.NotNull; +import org.labkey.api.assay.AssayDefaultFlagHandler; import org.labkey.api.data.ContainerManager; +import org.labkey.api.assay.AssayFlagHandler; import org.labkey.api.exp.api.ExperimentService; import org.labkey.api.exp.property.PropertyService; import org.labkey.api.module.DefaultModule; @@ -99,6 +101,13 @@ public void doStartup(ModuleContext moduleContext) ExperimentService.get().registerExperimentDataHandler(new SinglePlateDilutionNabDataHandler()); ContainerManager.addContainerListener(new NabContainerListener()); + // register QC flag handlers for supported assays + AssayFlagHandler handler = new AssayDefaultFlagHandler(); + + AssayFlagHandler.registerHandler(AssayService.get().getProvider(NabAssayProvider.NAME), handler); + AssayFlagHandler.registerHandler(new CrossPlateDilutionNabAssayProvider(), handler); + AssayFlagHandler.registerHandler(new SinglePlateDilutionNabAssayProvider(), handler); + PropertyService.get().registerDomainKind(new NabVirusDomainKind()); } diff --git a/nab/src/org/labkey/nab/query/NabProtocolSchema.java b/nab/src/org/labkey/nab/query/NabProtocolSchema.java index 32bce1d342..3bb58c7b22 100644 --- a/nab/src/org/labkey/nab/query/NabProtocolSchema.java +++ b/nab/src/org/labkey/nab/query/NabProtocolSchema.java @@ -30,18 +30,15 @@ import org.labkey.api.data.DatabaseCache; import org.labkey.api.data.DisplayColumn; import org.labkey.api.data.DisplayColumnFactory; -import org.labkey.api.data.JdbcType; import org.labkey.api.data.TableInfo; import org.labkey.api.exp.api.ExpProtocol; import org.labkey.api.exp.property.Domain; import org.labkey.api.exp.query.ExpRunTable; -import org.labkey.api.query.ExprColumn; import org.labkey.api.query.QuerySettings; import org.labkey.api.security.User; import org.labkey.api.study.assay.AssayDataLinkDisplayColumn; import org.labkey.api.study.assay.AssayProtocolSchema; import org.labkey.api.study.assay.AssayProvider; -import org.labkey.api.study.assay.AssayQCFlagColumn; import org.labkey.api.study.assay.RunListDetailsQueryView; import org.labkey.api.study.query.ResultsQueryView; import org.labkey.api.study.query.RunListQueryView; @@ -100,15 +97,6 @@ public DisplayColumn createRenderer(ColumnInfo colInfo) return runTable; } - @Override - protected void addQCFlagColumn(ExpRunTable runTable) - { - runTable.addColumn(new AssayQCFlagColumn(runTable, getSchemaName(), false)); - ColumnInfo qcEnabled = runTable.addColumn(new ExprColumn(runTable, "QCFlagsEnabled", AssayQCFlagColumn.createSQLFragment(runTable.getSqlDialect(), "Enabled"), JdbcType.VARCHAR)); - qcEnabled.setLabel("QC Flags Enabled State"); - qcEnabled.setHidden(true); - } - @Nullable @Override protected ResultsQueryView createDataQueryView(ViewContext context, QuerySettings settings, BindException errors) From ead401a3cfcc8ea83cc228e12678fecc5137569a Mon Sep 17 00:00:00 2001 From: klum Date: Tue, 7 May 2019 10:58:19 -0700 Subject: [PATCH 8/9] FK to QCState table Audit support for assay QC states enforce copy to study restrictions for unapproved QC --- luminex/src/org/labkey/luminex/LuminexDataHandler.java | 10 +++++----- nab/src/org/labkey/nab/NabAssayController.java | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/luminex/src/org/labkey/luminex/LuminexDataHandler.java b/luminex/src/org/labkey/luminex/LuminexDataHandler.java index 59fec122ed..c4ec6eaf0a 100644 --- a/luminex/src/org/labkey/luminex/LuminexDataHandler.java +++ b/luminex/src/org/labkey/luminex/LuminexDataHandler.java @@ -702,7 +702,7 @@ private void insertCVQCFlags(User user, ExpRun expRun, List data if (!newCVQCFlags.contains(newQcFlag)) { newCVQCFlags.add(newQcFlag); - AssayService.get().saveFlag(provider, newQcFlag, user); + AssayService.get().saveFlag(expRun.getContainer(), user, provider, newQcFlag); } } } @@ -852,7 +852,7 @@ public static void insertOrUpdateAnalyteSinglePointControlQCFlags(User user, Exp { if (!existingQCFlags.contains(newQCFlag)) { - AssayService.get().saveFlag(provider, newQCFlag, user); + AssayService.get().saveFlag(expRun.getContainer(), user, provider, newQCFlag); } } @@ -861,7 +861,7 @@ public static void insertOrUpdateAnalyteSinglePointControlQCFlags(User user, Exp { if (!newQCFlags.contains(existingAnalyteTitrationQCFlag)) { - AssayService.get().deleteFlags(provider, existingAnalyteTitrationQCFlag.getRowId(), user); + AssayService.get().deleteFlags(expRun.getContainer(), user, provider, existingAnalyteTitrationQCFlag.getRowId()); } } } @@ -1521,7 +1521,7 @@ else if (guideSetRow.isAucEnabled() && curveFit.getCurveType().equals("Trapezoid { if (!existingAnalyteTitrationQCFlags.contains(newAnalyteTitrationQCFlag)) { - AssayService.get().saveFlag(provider, newAnalyteTitrationQCFlag, user); + AssayService.get().saveFlag(expRun.getContainer(), user, provider, newAnalyteTitrationQCFlag); } } @@ -1530,7 +1530,7 @@ else if (guideSetRow.isAucEnabled() && curveFit.getCurveType().equals("Trapezoid { if (!newAnalyteTitrationQCFlags.contains(existingAnalyteTitrationQCFlag)) { - AssayService.get().deleteFlags(provider, existingAnalyteTitrationQCFlag.getRowId(), user); + AssayService.get().deleteFlags(expRun.getContainer(), user, provider, existingAnalyteTitrationQCFlag.getRowId()); } } } diff --git a/nab/src/org/labkey/nab/NabAssayController.java b/nab/src/org/labkey/nab/NabAssayController.java index 17b5f98da0..ee519ff83e 100644 --- a/nab/src/org/labkey/nab/NabAssayController.java +++ b/nab/src/org/labkey/nab/NabAssayController.java @@ -1055,7 +1055,7 @@ public ApiResponse execute(QCControlInfo form, BindException errors) throws Exce DilutionManager.clearWellExclusions(scope.getSqlDialect(), form.getRunId()); // clear out prior qc flags - AssayService.get().deleteFlags(provider, form.getRunId(), getUser()); + AssayService.get().deleteFlags(getContainer(), getUser(), provider, form.getRunId()); Set excludedWells = new HashSet<>(); Collection wellRowIds = new HashSet<>(); @@ -1065,7 +1065,7 @@ public ApiResponse execute(QCControlInfo form, BindException errors) throws Exce // add the assay qc flag for the exclusions NabWellQCFlag flag = new NabWellQCFlag(form.getRunId(), well); - AssayService.get().saveFlag(provider, flag, getUser()); + AssayService.get().saveFlag(getContainer(), getUser(), provider, flag); } // get the rowid's for the wells to exclude From 590df8d3544496856b4b8f6bb36b61911d36a4ea Mon Sep 17 00:00:00 2001 From: klum Date: Wed, 22 May 2019 11:55:37 -0700 Subject: [PATCH 9/9] fixes for Luminex tests --- luminex/src/org/labkey/luminex/LuminexDataHandler.java | 4 ++-- nab/src/org/labkey/nab/NabAssayController.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/luminex/src/org/labkey/luminex/LuminexDataHandler.java b/luminex/src/org/labkey/luminex/LuminexDataHandler.java index 5e9f86534a..3d9599149f 100644 --- a/luminex/src/org/labkey/luminex/LuminexDataHandler.java +++ b/luminex/src/org/labkey/luminex/LuminexDataHandler.java @@ -861,7 +861,7 @@ public static void insertOrUpdateAnalyteSinglePointControlQCFlags(User user, Exp { if (!newQCFlags.contains(existingAnalyteTitrationQCFlag)) { - AssayService.get().deleteFlags(expRun.getContainer(), user, provider, existingAnalyteTitrationQCFlag.getRowId()); + AssayService.get().deleteFlag(expRun.getContainer(), user, provider, existingAnalyteTitrationQCFlag); } } } @@ -1530,7 +1530,7 @@ else if (guideSetRow.isAucEnabled() && curveFit.getCurveType().equals("Trapezoid { if (!newAnalyteTitrationQCFlags.contains(existingAnalyteTitrationQCFlag)) { - AssayService.get().deleteFlags(expRun.getContainer(), user, provider, existingAnalyteTitrationQCFlag.getRowId()); + AssayService.get().deleteFlag(expRun.getContainer(), user, provider, existingAnalyteTitrationQCFlag); } } } diff --git a/nab/src/org/labkey/nab/NabAssayController.java b/nab/src/org/labkey/nab/NabAssayController.java index d833f567f6..ca4246374b 100644 --- a/nab/src/org/labkey/nab/NabAssayController.java +++ b/nab/src/org/labkey/nab/NabAssayController.java @@ -1055,7 +1055,7 @@ public ApiResponse execute(QCControlInfo form, BindException errors) throws Exce DilutionManager.clearWellExclusions(scope.getSqlDialect(), form.getRunId()); // clear out prior qc flags - AssayService.get().deleteFlags(getContainer(), getUser(), provider, form.getRunId()); + AssayService.get().deleteFlagsForRun(getContainer(), getUser(), provider, form.getRunId()); Set excludedWells = new HashSet<>(); Collection wellRowIds = new HashSet<>();