From 801ba053d64505c2ab879d892526f31eebab2f4d Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Wed, 29 Jul 2026 10:29:08 -0700 Subject: [PATCH] Address several optional feature issues --- api/src/org/labkey/api/query/QueryView.java | 10 +--------- .../api/settings/OptionalFeatureService.java | 10 +++++----- core/src/org/labkey/core/CoreModule.java | 18 +++++++++++++----- query/src/org/labkey/query/QueryModule.java | 2 -- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/api/src/org/labkey/api/query/QueryView.java b/api/src/org/labkey/api/query/QueryView.java index 1b054a1137e..9c0d584d721 100644 --- a/api/src/org/labkey/api/query/QueryView.java +++ b/api/src/org/labkey/api/query/QueryView.java @@ -146,8 +146,6 @@ */ public class QueryView extends WebPartView implements ContainerUser { - public static final String EXPERIMENTAL_GENERIC_DETAILS_URL = "generic-details-url"; - public static final String EXCEL_WEB_QUERY_EXPORT_TYPE = "excelWebQuery"; public static final String DATAREGIONNAME_DEFAULT = "query"; @@ -3012,12 +3010,6 @@ protected ContainerFilter getContainerFilter() return null; } - private boolean isShowExperimentalGenericDetailsURL() - { - return AppProps.getInstance().isOptionalFeatureEnabled(EXPERIMENTAL_GENERIC_DETAILS_URL); - } - - List _queryDefDisplayColumns = null; public List getDisplayColumns() @@ -3050,7 +3042,7 @@ protected void addDetailsAndUpdateColumns(List ret, TableInfo tab if (isPrintView() || isExportView()) return; - if (_showDetailsColumn && (null != _detailsURL || table.hasDetailsURL() || isShowExperimentalGenericDetailsURL())) + if (_showDetailsColumn && (null != _detailsURL || table.hasDetailsURL())) { StringExpression urlDetails = urlExpr(QueryAction.detailsQueryRow); diff --git a/api/src/org/labkey/api/settings/OptionalFeatureService.java b/api/src/org/labkey/api/settings/OptionalFeatureService.java index 5444d834240..81e0ef342ed 100644 --- a/api/src/org/labkey/api/settings/OptionalFeatureService.java +++ b/api/src/org/labkey/api/settings/OptionalFeatureService.java @@ -49,8 +49,7 @@ static void setInstance(OptionalFeatureService impl) /** * @param flag must be unique and conform to the Java identifier rules (e.g., alphanumeric plus _, start with a - * letter, no spaces). That way it can be used as a startup property to enable/disable the task. If - * you must use a flag that doesn't conform to these rules (why?) the call the other variant. + * letter, no spaces) so it can be used as a startup property to enable/disable the task. */ default void addExperimentalFeatureFlag(String flag, String title, String description, boolean requiresRestart) { @@ -58,8 +57,9 @@ default void addExperimentalFeatureFlag(String flag, String title, String descri } /** - * This is left for backward compatibility. Use the variant above and provide flag that follows Java identifier rules. + * This is left for backward compatibility. Use the variant above and provide a flag that follows Java identifier rules. */ + @Deprecated default void addExperimentalFeatureFlag(String flag, String title, String description, boolean requiresRestart, boolean useDumbName) { addFeatureFlag(new OptionalFeatureFlag(flag, title, description, requiresRestart, false, FeatureType.Experimental, useDumbName)); @@ -127,8 +127,8 @@ public HtmlString getAdminGuidance() { return HtmlString.unsafe( """ - Optional features are not typically used; discuss with your account manager before enabling any - optional feature. + Optional features are disabled by default. Review the description for each feature before enabling + it, and discuss with your Account Manager if you have questions. """ ); } diff --git a/core/src/org/labkey/core/CoreModule.java b/core/src/org/labkey/core/CoreModule.java index 44b4e02c3a3..86dddbcda11 100644 --- a/core/src/org/labkey/core/CoreModule.java +++ b/core/src/org/labkey/core/CoreModule.java @@ -1146,21 +1146,29 @@ public void moduleStartupComplete(ServletContext servletContext) .filter(DataLoaderFactory::indexable) .forEach(ss::addDocumentParser); - OptionalFeatureService.get().addExperimentalFeatureFlag(AppProps.EXPERIMENTAL_NO_GUESTS, + OptionalFeatureService.get().addFeatureFlag(new OptionalFeatureFlag( + AppProps.EXPERIMENTAL_NO_GUESTS, "No Guest Account", "Disable the guest account", - false); + false, + false, + FeatureType.Optional + )); OptionalFeatureService.get().addExperimentalFeatureFlag(AppProps.EXPERIMENTAL_BLOCKER, "Block malicious clients", "Reject requests from clients that appear malicious. Turn this feature off if you want to run a security scanner.", false); - OptionalFeatureService.get().addExperimentalFeatureFlag(FEATURE_FLAG_DISABLE_ENFORCE_CSP, + OptionalFeatureService.get().addFeatureFlag(new OptionalFeatureFlag( + FEATURE_FLAG_DISABLE_ENFORCE_CSP, "Disable enforce Content Security Policy", "Stop sending the " + ContentSecurityPolicyFilter.ContentSecurityPolicyType.Enforce.getHeaderName() + " header to browsers, " + "but continue sending the " + ContentSecurityPolicyFilter.ContentSecurityPolicyType.Report.getHeaderName() + " header. " + "This turns off an important layer of security for the entire site, so use it as a last resort only on a temporary basis " + "(e.g., if an enforce CSP breaks critical functionality).", - false); + false, + false, + FeatureType.Deprecated + )); OptionalFeatureService.get().addExperimentalFeatureFlag(DataRegion.EXPERIMENTAL_DATA_REGION_ASYNC_TOTAL_ROWS, "Data Region Async Total Rows", "Enable asynchronous calculation of total rows for data regions. This can improve performance for large datasets.", @@ -1168,7 +1176,7 @@ public void moduleStartupComplete(ServletContext servletContext) OptionalFeatureService.get().addFeatureFlag(new OptionalFeatureFlag(EXPERIMENTAL_LOCAL_MARKETING_UPDATE, "Self test marketing updates", "Test marketing updates from this local server (requires the mothership module).", false, true, FeatureType.Experimental)); - OptionalFeatureService.get().addFeatureListener(EXPERIMENTAL_LOCAL_MARKETING_UPDATE, (feature, enabled) -> { + OptionalFeatureService.get().addFeatureListener(EXPERIMENTAL_LOCAL_MARKETING_UPDATE, (_, enabled) -> { // update the timer task when this setting changes MothershipReport.setSelfTestMarketingUpdates(enabled); UsageReportingLevel.reportNow(); diff --git a/query/src/org/labkey/query/QueryModule.java b/query/src/org/labkey/query/QueryModule.java index 3a6b7391bda..3a03809f167 100644 --- a/query/src/org/labkey/query/QueryModule.java +++ b/query/src/org/labkey/query/QueryModule.java @@ -237,8 +237,6 @@ public QuerySchema createSchema(DefaultSchema schema, Module module) DataViewService.get().registerProvider(QueryDataViewProvider.TYPE, new QueryDataViewProvider()); DataViewService.get().registerProvider(InheritedQueryDataViewProvider.TYPE, new InheritedQueryDataViewProvider()); - OptionalFeatureService.get().addExperimentalFeatureFlag(QueryView.EXPERIMENTAL_GENERIC_DETAILS_URL, "Generic [details] link in grids/queries", - "This feature will turn on generating a generic [details] URL link in most grids.", false, true); OptionalFeatureService.get().addExperimentalFeatureFlag(QueryServiceImpl.EXPERIMENTAL_LAST_MODIFIED, "Include Last-Modified header on query metadata requests", "For schema, query, and view metadata requests include a Last-Modified header such that the browser can cache the response. " + "The metadata is invalidated when performing actions such as creating a new List or modifying the columns on a custom view", false);