Skip to content

Commit 5cf0aac

Browse files
vagishaclaude
andauthored
Restrict library spectra for guest users on large spectrum libraries (#1226)
- Do not show library spectra to guests when the spectrum library file is ≥ 500 MB; show the existing "Login to view this data" message instead. - The restriction applies to all library-read paths (the spectrum panel, the spectrum AJAX endpoint, and the chromatogram peptide-ID retention-time markers). - Logged-in users and small libraries are unaffected. Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]>
1 parent 8d289d2 commit 5cf0aac

3 files changed

Lines changed: 101 additions & 0 deletions

File tree

src/org/labkey/targetedms/TargetedMSController.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3232,8 +3232,31 @@ public void addNavTrail(NavTree root)
32323232
}
32333233
}
32343234

3235+
/**
3236+
* Reading library spectra from a large library file can take many seconds over network storage, especially for large
3237+
* EncyclopeDIA libraries. To protect public folders from aggressive bots, do not show library spectra to guests when
3238+
* the library is large. Show the login prompt instead.
3239+
* Returns true (and adds the login view) when the library spectrum should be withheld.
3240+
*/
3241+
private boolean addGuestSpectrumGate(TargetedMSRun run, VBox vbox)
3242+
{
3243+
if (!LibrarySpectrumMatchGetter.blockSpectraForGuest(getUser(), run.getId()))
3244+
{
3245+
return false;
3246+
}
3247+
HtmlView loginView = getLoginView(getViewContext(), getContainer());
3248+
loginView.setTitle("Library Spectrum");
3249+
loginView.setFrame(WebPartView.FrameType.PORTAL);
3250+
vbox.addView(loginView);
3251+
return true;
3252+
}
3253+
32353254
private void addSpectrumViews(TargetedMSRun run, VBox vbox, Precursor precursor, BindException errors)
32363255
{
3256+
if (addGuestSpectrumGate(run, vbox))
3257+
{
3258+
return;
3259+
}
32373260
PipeRoot root = PipelineService.get().getPipelineRootSetting(getContainer());
32383261
if (null != root)
32393262
{
@@ -3252,6 +3275,10 @@ private void addSpectrumViews(TargetedMSRun run, VBox vbox, Precursor precursor,
32523275

32533276
private void addSpectrumViews(TargetedMSRun run, VBox vbox, Peptide peptide, BindException errors)
32543277
{
3278+
if (addGuestSpectrumGate(run, vbox))
3279+
{
3280+
return;
3281+
}
32553282
PipeRoot root = PipelineService.get().getPipelineRootSetting(getContainer());
32563283
if (null != root)
32573284
{
@@ -3336,6 +3363,13 @@ public Object execute(SpectrumDataForm form, BindException errors)
33363363
}
33373364
TargetedMSRun run = TargetedMSManager.getRunForGeneralMolecule(peptide.getId());
33383365

3366+
// Apply the same guest gate as the spectrum views (see LibrarySpectrumMatchGetter.blockSpectraForGuest).
3367+
if (LibrarySpectrumMatchGetter.blockSpectraForGuest(getUser(), run.getId()))
3368+
{
3369+
response.put("error", "Login to view this data");
3370+
return response;
3371+
}
3372+
33393373
List<PeptideSettings.SpectrumLibrary> libraries = LibraryManager.getLibraries(run.getId());
33403374
PeptideSettings.SpectrumLibrary library = null;
33413375
for (PeptideSettings.SpectrumLibrary lib : libraries)

src/org/labkey/targetedms/chart/ChromatogramDataset.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,13 @@ public void build()
901901

902902
protected List<LibrarySpectrumMatchGetter.PeptideIdRtInfo> getPeptideIdRetentionTimes()
903903
{
904+
// Skip peptide-ID retention-time markers for guests when the library is large. Reading large libraries can be slow over network storage.
905+
// See LibrarySpectrumMatchGetter.blockSpectraForGuest.
906+
if (LibrarySpectrumMatchGetter.blockSpectraForGuest(_user, _run.getId()))
907+
{
908+
return Collections.emptyList();
909+
}
910+
904911
SampleFile sampleFile = ReplicateManager.getSampleFile(_pChromInfo.getSampleFileId());
905912

906913
// TODO: May want to move LocalDirectory up to controller, where others are created. Sharing probably desired.

src/org/labkey/targetedms/view/spectrum/LibrarySpectrumMatchGetter.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.labkey.targetedms.view.spectrum;
1717

1818
import org.apache.commons.io.FilenameUtils;
19+
import org.apache.logging.log4j.Logger;
1920
import org.jetbrains.annotations.NotNull;
2021
import org.jetbrains.annotations.Nullable;
2122
import org.labkey.api.cache.BlockingCache;
@@ -24,6 +25,7 @@
2425
import org.labkey.api.data.Container;
2526
import org.labkey.api.security.User;
2627
import org.labkey.api.util.FileUtil;
28+
import org.labkey.api.util.logging.LogHelper;
2729
import org.labkey.targetedms.TargetedMSManager;
2830
import org.labkey.targetedms.TargetedMSRun;
2931
import org.labkey.targetedms.TargetedMSSchema;
@@ -42,6 +44,8 @@
4244
import org.labkey.targetedms.query.PeptideManager;
4345
import org.labkey.targetedms.query.PrecursorManager;
4446

47+
import java.io.IOException;
48+
import java.nio.file.Files;
4549
import java.nio.file.Path;
4650
import java.sql.SQLException;
4751
import java.util.ArrayList;
@@ -59,8 +63,64 @@
5963
*/
6064
public class LibrarySpectrumMatchGetter
6165
{
66+
private static final Logger LOG = LogHelper.getLogger(LibrarySpectrumMatchGetter.class, "Matches library spectra and retention times for the library spectrum viewer");
67+
6268
private static final int CACHE_SIZE = 10;
6369

70+
// Reading library spectra and retention times from large spectrum libraries can be slow over network storage.
71+
// For EncyclopeDIA .elib we read one row per source file for the peptide. This can be hundreds of rows and the needed
72+
// columns are not in the index, so each table row lookup is a separate network round-trip on GPFS.
73+
// For BiblioSpec .blib we scan the unindexed RetentionTimes table for the RT of the peptide in all the scans and source
74+
// files.
75+
// PanoramaWeb has large files of both types, so the size gate covers both library types. To protect public folders from
76+
// aggressive bots, library spectra are not shown to guests when the library file is at or above this size. Guests are
77+
// asked to log in instead.
78+
private static final long GUEST_SPECTRUM_LIBRARY_SIZE_LIMIT = 500L * 1024 * 1024; // 500 MB
79+
80+
/**
81+
* Returns true if library spectra should NOT be shown to the given user for the given run,
82+
* i.e. the user is a guest and the run references a supported spectrum library file that is at
83+
* or above {@link #GUEST_SPECTRUM_LIBRARY_SIZE_LIMIT}. Logged-in users are never blocked, and
84+
* small libraries are read in place as before.
85+
*/
86+
public static boolean blockSpectraForGuest(User user, long runId)
87+
{
88+
if (!user.isGuest())
89+
{
90+
return false;
91+
}
92+
for (Path libPath : LibraryManager.getLibraryFilePaths(runId).values())
93+
{
94+
if (isLargeSpectrumLibrary(libPath))
95+
{
96+
return true;
97+
}
98+
}
99+
return false;
100+
}
101+
102+
private static boolean isLargeSpectrumLibrary(Path libPath)
103+
{
104+
// Only .elib/.blib libraries are read for spectra; ignore anything we cannot read.
105+
if (libPath == null || getReaderForLibrary(FileUtil.getFileName(libPath)) == null)
106+
{
107+
return false;
108+
}
109+
try
110+
{
111+
// Files.size throws NoSuchFileException if the file is missing, so a separate Files.exists
112+
// check is unnecessary and would add a second filesystem round-trip on network storage.
113+
return Files.size(libPath) >= GUEST_SPECTRUM_LIBRARY_SIZE_LIMIT;
114+
}
115+
catch (IOException e)
116+
{
117+
// If we cannot stat the file it is missing or unreadable, in which case the
118+
// downstream library read will fail too.
119+
LOG.warn("Could not determine size of spectrum library file " + libPath, e);
120+
return false;
121+
}
122+
}
123+
64124
private static final BlockingCache<PrecursorKey, List<PeptideIdRtInfo>> _peptideIdRtsCache =
65125
CacheManager.getBlockingCache(CACHE_SIZE, CacheManager.DAY, "TargetedMS peptide ID retention times",
66126
(precursor, argument) -> {

0 commit comments

Comments
 (0)