• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IQSS / dataverse / #22985

23 Aug 2024 06:32PM CUT coverage: 20.61% (-0.2%) from 20.791%
#22985

Pull #10781

github

landreev
added an upfront locks check to the /addGlobusFiles api #10623
Pull Request #10781: Improved handling of Globus uploads

4 of 417 new or added lines in 15 files covered. (0.96%)

4194 existing lines in 35 files now uncovered.

17388 of 84365 relevant lines covered (20.61%)

0.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

19.55
/src/main/java/edu/harvard/iq/dataverse/util/SystemConfig.java
1
package edu.harvard.iq.dataverse.util;
2

3
import com.ocpsoft.pretty.PrettyContext;
4
import edu.harvard.iq.dataverse.DataFile;
5
import edu.harvard.iq.dataverse.Dataverse;
6
import edu.harvard.iq.dataverse.DataverseServiceBean;
7
import edu.harvard.iq.dataverse.DvObjectContainer;
8
import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean;
9
import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinAuthenticationProvider;
10
import edu.harvard.iq.dataverse.authorization.providers.oauth2.AbstractOAuth2AuthenticationProvider;
11
import edu.harvard.iq.dataverse.settings.JvmSettings;
12
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
13
import edu.harvard.iq.dataverse.validation.PasswordValidatorUtil;
14
import org.passay.CharacterRule;
15

16
import jakarta.ejb.EJB;
17
import jakarta.ejb.Stateless;
18
import jakarta.inject.Named;
19
import jakarta.json.Json;
20
import jakarta.json.JsonArray;
21
import jakarta.json.JsonObject;
22
import jakarta.json.JsonReader;
23
import jakarta.json.JsonString;
24
import jakarta.json.JsonValue;
25
import java.io.StringReader;
26
import java.net.InetAddress;
27
import java.net.UnknownHostException;
28
import java.time.Year;
29
import java.util.Arrays;
30
import java.util.HashMap;
31
import java.util.Iterator;
32
import java.util.List;
33
import java.util.Map;
34
import java.util.MissingResourceException;
35
import java.util.Optional;
36
import java.util.ResourceBundle;
37
import java.util.logging.Logger;
38
import java.util.regex.Matcher;
39
import java.util.regex.Pattern;
40

41
/**
42
 * System-wide configuration
43
 */
44
@Stateless
45
@Named
46
public class SystemConfig {
1✔
47

48
    private static final Logger logger = Logger.getLogger(SystemConfig.class.getCanonicalName());
1✔
49

50
    @EJB
51
    SettingsServiceBean settingsService;
52

53
    @EJB
54
    DataverseServiceBean dataverseService;
55

56
    @EJB
57
    AuthenticationServiceBean authenticationService;
58
    
59
   public static final String DATAVERSE_PATH = "/dataverse/";
60
   
61
    /**
62
     * Some installations may not want download URLs to their files to be
63
     * available in Schema.org JSON-LD output.
64
     */
65
    public static final String FILES_HIDE_SCHEMA_DOT_ORG_DOWNLOAD_URLS = "dataverse.files.hide-schema-dot-org-download-urls";
66

67
    /**
68
     * A JVM option to override the number of minutes for which a password reset
69
     * token is valid ({@link #getMinutesUntilPasswordResetTokenExpires}).
70
     */
71
    private static final String PASSWORD_RESET_TIMEOUT_IN_MINUTES = "dataverse.auth.password-reset-timeout-in-minutes";
72

73
    /**
74
     * The default number of datafiles that we allow to be created through 
75
     * zip file upload.
76
     */
77
    private static final int defaultZipUploadFilesLimit = 1000; 
78
    public static final long defaultZipDownloadLimit = 104857600L; // 100MB
79
    private static final int defaultMultipleUploadFilesLimit = 1000;
80
    private static final int defaultLoginSessionTimeout = 480; // = 8 hours
81
    
82
    private String buildNumber = null;
1✔
83
    
84
    private static final String JVM_TIMER_SERVER_OPTION = "dataverse.timerServer";
85
    
86
    private static final long DEFAULT_GUESTBOOK_RESPONSES_DISPLAY_LIMIT = 5000L; 
87
    private static final long DEFAULT_THUMBNAIL_SIZE_LIMIT_IMAGE = 3000000L; // 3 MB
88
    private static final long DEFAULT_THUMBNAIL_SIZE_LIMIT_PDF = 1000000L; // 1 MB
89
    
90
    public final static String DEFAULTCURATIONLABELSET = "DEFAULT";
91
    public final static String CURATIONLABELSDISABLED = "DISABLED";
92
    
93
    public String getVersion() {
94
        return getVersion(false);
1✔
95
    }
96
    
97
    // The return value is a "prviate static String", that should be initialized
98
    // once, on the first call (see the code below)... But this is a @Stateless 
99
    // bean... so that would mean "once per thread"? - this would be a prime 
100
    // candidate for being moved into some kind of an application-scoped caching
101
    // service... some CachingService @Singleton - ? (L.A. 5.8)
102
    public String getVersion(boolean withBuildNumber) {
103
        // Retrieve the version via MPCONFIG
104
        // NOTE: You may override the version via all methods of MPCONFIG.
105
        //       It will default to read from microprofile-config.properties source,
106
        //       which contains in the source a Maven property reference to ${project.version}.
107
        //       When packaging the app to deploy it, Maven will replace this, rendering it a static entry.
108
        String appVersion = JvmSettings.VERSION.lookup();
1✔
109
            
110
        if (withBuildNumber) {
1✔
111
            if (buildNumber == null) {
1✔
112
                // (build number is still in a .properties file in the source tree; it only
113
                // contains a real build number if this war file was built by Jenkins)
114
                // TODO: might be replaced with same trick as for version via Maven property w/ empty default
115
                try {
116
                    buildNumber = ResourceBundle.getBundle("BuildNumber").getString("build.number");
×
117
                } catch (MissingResourceException ex) {
1✔
118
                    buildNumber = null;
1✔
119
                }
×
120
                
121
                // Also try to read the build number via MicroProfile Config if not already present from the
122
                // properties file (so can be overridden by env var or other source)
123
                if (buildNumber == null || buildNumber.isEmpty()) {
1✔
124
                    buildNumber = JvmSettings.BUILD.lookupOptional().orElse("");
1✔
125
                }
126
            }
127
            
128
            if (!buildNumber.equals("")) {
1✔
129
                return appVersion + " build " + buildNumber;
1✔
130
            }
131
        }
132
        
133
        return appVersion;
1✔
134
    }
135
    
136
    /**
137
     * Retrieve the Solr endpoint in "host:port" form, to be used with a Solr client.
138
     *
139
     * This will retrieve the setting from either the database ({@link SettingsServiceBean.Key#SolrHostColonPort}) or
140
     * via Microprofile Config API (properties {@link JvmSettings#SOLR_HOST} and {@link JvmSettings#SOLR_PORT}).
141
     *
142
     * A database setting always takes precedence. If not given via other config sources, a default from
143
     * <code>resources/META-INF/microprofile-config.properties</code> is used. (It's possible to use profiles.)
144
     *
145
     * @return Solr endpoint as string "hostname:port"
146
     */
147
    public String getSolrHostColonPort() {
148
        // Get from MPCONFIG. Might be configured by a sysadmin or simply return the default shipped with
149
        // resources/META-INF/microprofile-config.properties.
150
        // NOTE: containers should use system property mp.config.profile=ct to use sane container usage default
151
        String host = JvmSettings.SOLR_HOST.lookup();
1✔
152
        String port = JvmSettings.SOLR_PORT.lookup();
1✔
153
        
154
        // DB setting takes precedence over all. If not present, will return default from above.
155
        return Optional.ofNullable(settingsService.getValueForKey(SettingsServiceBean.Key.SolrHostColonPort))
1✔
156
            .orElse(host + ":" + port);
1✔
157
    }
158

159
    public boolean isProvCollectionEnabled() {
160
        String provCollectionEnabled = settingsService.getValueForKey(SettingsServiceBean.Key.ProvCollectionEnabled, null);
×
161
        if("true".equalsIgnoreCase(provCollectionEnabled)){         
×
162
            return true;
×
163
        }
164
        return false;
×
165

166
    }
167
    
168
    public int getMetricsCacheTimeoutMinutes() {
169
        int defaultValue = 10080; //one week in minutes
×
170
        SettingsServiceBean.Key key = SettingsServiceBean.Key.MetricsCacheTimeoutMinutes;
×
171
        String metricsCacheTimeString = settingsService.getValueForKey(key);
×
172
        if (metricsCacheTimeString != null) {
×
173
            int returnInt = 0;
×
174
            try {
175
                returnInt = Integer.parseInt(metricsCacheTimeString);
×
176
                if (returnInt >= 0) {
×
177
                    return returnInt;
×
178
                } else {
179
                    logger.info("Returning " + defaultValue + " for " + key + " because value must be greater than zero, not \"" + metricsCacheTimeString + "\".");
×
180
                }
181
            } catch (NumberFormatException ex) {
×
182
                logger.info("Returning " + defaultValue + " for " + key + " because value must be an integer greater than zero, not \"" + metricsCacheTimeString + "\".");
×
183
            }
×
184
        }
185
        return defaultValue;
×
186
    }
187
    
188
    public int getMinutesUntilConfirmEmailTokenExpires() {
189
        final int minutesInOneDay = 1440;
×
190
        final int reasonableDefault = minutesInOneDay;
×
191
        SettingsServiceBean.Key key = SettingsServiceBean.Key.MinutesUntilConfirmEmailTokenExpires;
×
192
        String valueFromDatabase = settingsService.getValueForKey(key);
×
193
        if (valueFromDatabase != null) {
×
194
            try {
195
                int intFromDatabase = Integer.parseInt(valueFromDatabase);
×
196
                if (intFromDatabase > 0) {
×
197
                    return intFromDatabase;
×
198
                } else {
199
                    logger.info("Returning " + reasonableDefault + " for " + key + " because value must be greater than zero, not \"" + intFromDatabase + "\".");
×
200
                }
201
            } catch (NumberFormatException ex) {
×
202
                logger.info("Returning " + reasonableDefault + " for " + key + " because value must be an integer greater than zero, not \"" + valueFromDatabase + "\".");
×
203
            }
×
204
        }
205
        logger.fine("Returning " + reasonableDefault + " for " + key);
×
206
        return reasonableDefault;
×
207
    }
208

209
    /**
210
     * The number of minutes for which a password reset token is valid. Can be
211
     * overridden by {@link #PASSWORD_RESET_TIMEOUT_IN_MINUTES}.
212
     */
213
    public static int getMinutesUntilPasswordResetTokenExpires() {
214
        final int reasonableDefault = 60;
1✔
215
        String configuredValueAsString = System.getProperty(PASSWORD_RESET_TIMEOUT_IN_MINUTES);
1✔
216
        if (configuredValueAsString != null) {
1✔
217
            int configuredValueAsInteger = 0;
×
218
            try {
219
                configuredValueAsInteger = Integer.parseInt(configuredValueAsString);
×
220
                if (configuredValueAsInteger > 0) {
×
221
                    return configuredValueAsInteger;
×
222
                } else {
223
                    logger.info(PASSWORD_RESET_TIMEOUT_IN_MINUTES + " is configured as a negative number \"" + configuredValueAsInteger + "\". Using default value instead: " + reasonableDefault);
×
224
                    return reasonableDefault;
×
225
                }
226
            } catch (NumberFormatException ex) {
×
227
                logger.info("Unable to convert " + PASSWORD_RESET_TIMEOUT_IN_MINUTES + " from \"" + configuredValueAsString + "\" into an integer value: " + ex + ". Using default value " + reasonableDefault);
×
228
            }
229
        }
230
        return reasonableDefault;
1✔
231
    }
232
    
233
    /**
234
     * Lookup (or construct) the designated URL of this instance from configuration.
235
     *
236
     * Can be defined as a complete URL via <code>dataverse.siteUrl</code>; or derived from the hostname
237
     * <code>dataverse.fqdn</code> and HTTPS. If none of these options is set, defaults to the
238
     * {@link InetAddress#getLocalHost} and HTTPS.
239
     *
240
     * NOTE: This method does not provide any validation.
241
     * TODO: The behaviour of this method is subject to a later change, see
242
     *       https://github.com/IQSS/dataverse/issues/6636
243
     *
244
     * @return The designated URL of this instance as per configuration.
245
     */
246
    public String getDataverseSiteUrl() {
247
        return getDataverseSiteUrlStatic();
×
248
    }
249
    
250
    /**
251
     * Lookup (or construct) the designated URL of this instance from configuration.
252
     *
253
     * Can be defined as a complete URL via <code>dataverse.siteUrl</code>; or derived from the hostname
254
     * <code>dataverse.fqdn</code> and HTTPS. If none of these options is set, defaults to the
255
     * {@link InetAddress#getLocalHost} and HTTPS.
256
     *
257
     * NOTE: This method does not provide any validation.
258
     * TODO: The behaviour of this method is subject to a later change, see
259
     *       https://github.com/IQSS/dataverse/issues/6636
260
     *
261
     * @return The designated URL of this instance as per configuration.
262
     */
263
    public static String getDataverseSiteUrlStatic() {
264
        // If dataverse.siteUrl has been configured, simply return it
265
        Optional<String> siteUrl = JvmSettings.SITE_URL.lookupOptional();
1✔
266
        if (siteUrl.isPresent()) {
1✔
267
            return siteUrl.get();
1✔
268
        }
269
        
270
        // Otherwise try to lookup dataverse.fqdn setting and default to HTTPS
271
        Optional<String> fqdn = JvmSettings.FQDN.lookupOptional();
1✔
272
        if (fqdn.isPresent()) {
1✔
273
            return "https://" + fqdn.get();
×
274
        }
275
        
276
        // Last resort - get the servers local name and use it.
277
        // BEWARE - this is dangerous.
278
        // 1) A server might have a different name than your repository URL.
279
        // 2) The underlying reverse DNS lookup might point to a different name than your repository URL.
280
        // 3) If this server has multiple IPs assigned, which one will it be for the lookup?
281
        try {
282
            return "https://" + InetAddress.getLocalHost().getCanonicalHostName();
1✔
283
        } catch (UnknownHostException e) {
×
284
            return null;
×
285
        }
286
    }
287
    
288
    /**
289
     * URL Tracking: 
290
     */
291
    public String getPageURLWithQueryString() {
292
        return PrettyContext.getCurrentInstance().getRequestURL().toURL() + PrettyContext.getCurrentInstance().getRequestQueryString().toQueryString();
×
293
    }
294

295
    public String getGuidesBaseUrl() {
296
        String saneDefault = "https://guides.dataverse.org";
×
297
        String guidesBaseUrl = settingsService.getValueForKey(SettingsServiceBean.Key.GuidesBaseUrl, saneDefault);
×
298
        return guidesBaseUrl + "/" + getGuidesLanguage();
×
299
    }
300

301
    private String getGuidesLanguage() {
302
        String saneDefault = "en";
×
303
        return saneDefault;
×
304
    }
305

306
    public String getGuidesVersion() {
307
        String saneDefault = getVersion();
×
308
        String guidesVersion = settingsService.getValueForKey(SettingsServiceBean.Key.GuidesVersion, saneDefault);
×
309
        if (guidesVersion != null) {
×
310
            return guidesVersion;
×
311
        }
312
        return saneDefault;
×
313
    }
314

315
    public String getMetricsUrl() {
316
        String saneDefault = null;
×
317
        String metricsUrl = settingsService.getValueForKey(SettingsServiceBean.Key.MetricsUrl, saneDefault);
×
318
        return metricsUrl;
×
319
    }
320

321
    public static long getLongLimitFromStringOrDefault(String limitSetting, Long defaultValue) {
322
        Long limit = null;
1✔
323

324
        if (limitSetting != null && !limitSetting.equals("")) {
1✔
325
            try {
326
                limit = Long.valueOf(limitSetting);
1✔
327
            } catch (NumberFormatException nfe) {
1✔
328
                limit = null;
1✔
329
            }
1✔
330
        }
331

332
        return limit != null ? limit : defaultValue;
1✔
333
    }
334

335
    public static int getIntLimitFromStringOrDefault(String limitSetting, Integer defaultValue) {
336
        Integer limit = null;
1✔
337

338
        if (limitSetting != null && !limitSetting.equals("")) {
1✔
339
            try {
340
                limit = Integer.valueOf(limitSetting);
1✔
341
            } catch (NumberFormatException nfe) {
1✔
342
                limit = null;
1✔
343
            }
1✔
344
        }
345

346
        return limit != null ? limit : defaultValue;
1✔
347
    }
348

349
    /**
350
     * Download-as-zip size limit.
351
     * returns defaultZipDownloadLimit if not specified; 
352
     * set to -1 to disable zip downloads. 
353
     */
354
    public long getZipDownloadLimit() {
355
        String zipLimitOption = settingsService.getValueForKey(SettingsServiceBean.Key.ZipDownloadLimit);
×
356
        return getLongLimitFromStringOrDefault(zipLimitOption, defaultZipDownloadLimit);
×
357
    }
358
    
359
    public int getZipUploadFilesLimit() {
360
        String limitOption = settingsService.getValueForKey(SettingsServiceBean.Key.ZipUploadFilesLimit);
×
361
        return getIntLimitFromStringOrDefault(limitOption, defaultZipUploadFilesLimit);
×
362
    }
363
    
364
    /**
365
     * Session timeout, in minutes. 
366
     * (default value provided)
367
     */
368
    public int getLoginSessionTimeout() {
369
        return getIntLimitFromStringOrDefault(
×
370
                settingsService.getValueForKey(SettingsServiceBean.Key.LoginSessionTimeout), 
×
371
                defaultLoginSessionTimeout); 
×
372
    }
373
    
374
    /*
375
    `   the number of files the GUI user is allowed to upload in one batch, 
376
        via drag-and-drop, or through the file select dialog
377
    */
378
    public int getMultipleUploadFilesLimit() {
379
        String limitOption = settingsService.getValueForKey(SettingsServiceBean.Key.MultipleUploadFilesLimit);
×
380
        return getIntLimitFromStringOrDefault(limitOption, defaultMultipleUploadFilesLimit);
×
381
    }
382
    
383
    public long getGuestbookResponsesPageDisplayLimit() {
384
        String limitSetting = settingsService.getValueForKey(SettingsServiceBean.Key.GuestbookResponsesPageDisplayLimit);
×
385
        return getLongLimitFromStringOrDefault(limitSetting, DEFAULT_GUESTBOOK_RESPONSES_DISPLAY_LIMIT);
×
386
    }
387
    
388
    public long getUploadLogoSizeLimit(){
389
        return 500000;
×
390
    }
391

392
    public long getThumbnailSizeLimitImage() {
393
        return getThumbnailSizeLimit("Image");
×
394
    }
395

396
    public long getThumbnailSizeLimitPDF() {
397
        return getThumbnailSizeLimit("PDF");
×
398
    }
399

400
    public static long getThumbnailSizeLimit(String type) {
401
        String option = null; 
1✔
402
        
403
        //get options via jvm options
404
        
405
        if ("Image".equals(type)) {
1✔
406
            option = System.getProperty("dataverse.dataAccess.thumbnail.image.limit");
1✔
407
            return getLongLimitFromStringOrDefault(option, DEFAULT_THUMBNAIL_SIZE_LIMIT_IMAGE);
1✔
408
        } else if ("PDF".equals(type)) {
1✔
409
            option = System.getProperty("dataverse.dataAccess.thumbnail.pdf.limit");
1✔
410
            return getLongLimitFromStringOrDefault(option, DEFAULT_THUMBNAIL_SIZE_LIMIT_PDF);
1✔
411
        }
412

413
        // Zero (0) means no limit.
414
        return getLongLimitFromStringOrDefault(option, 0L);
1✔
415
    }
416
    
417
    public boolean isThumbnailGenerationDisabledForType(String type) {
418
        return getThumbnailSizeLimit(type) == -1l;
×
419
    }
420
    
421
    public boolean isThumbnailGenerationDisabledForImages() {
422
        return isThumbnailGenerationDisabledForType("Image");
×
423
    }
424
    
425
    public boolean isThumbnailGenerationDisabledForPDF() {
426
        return isThumbnailGenerationDisabledForType("PDF");
×
427
    }
428
    
429
    public String getApplicationTermsOfUse() {
430
        String language = BundleUtil.getCurrentLocale().getLanguage();
×
431
        String saneDefaultForAppTermsOfUse = BundleUtil.getStringFromBundle("system.app.terms");
×
432
        // Get the value for the defaultLocale. IT will either be used as the return
433
        // value, or as a better default than the saneDefaultForAppTermsOfUse if there
434
        // is no language-specific value
435
        String appTermsOfUse = settingsService.getValueForKey(SettingsServiceBean.Key.ApplicationTermsOfUse, saneDefaultForAppTermsOfUse);
×
436
        //Now get the language-specific value if it exists
437
        if (language != null && !language.equalsIgnoreCase(BundleUtil.getDefaultLocale().getLanguage())) {
×
438
            appTermsOfUse = settingsService.getValueForKey(SettingsServiceBean.Key.ApplicationTermsOfUse, language,        appTermsOfUse);
×
439
        }
440
        return appTermsOfUse;
×
441
    }
442

443
    public String getApiTermsOfUse() {
444
        String saneDefaultForApiTermsOfUse = BundleUtil.getStringFromBundle("system.api.terms");
×
445
        String apiTermsOfUse = settingsService.getValueForKey(SettingsServiceBean.Key.ApiTermsOfUse, saneDefaultForApiTermsOfUse);
×
446
        return apiTermsOfUse;
×
447
    }
448

449
    // TODO: 
450
    // remove this method!
451
    // pages should be using settingsWrapper.get(":ApplicationPrivacyPolicyUrl") instead. -- 4.2.1
452
    public String getApplicationPrivacyPolicyUrl() {
453
        String saneDefaultForPrivacyPolicyUrl = null;
×
454
        String appPrivacyPolicyUrl = settingsService.getValueForKey(SettingsServiceBean.Key.ApplicationPrivacyPolicyUrl, saneDefaultForPrivacyPolicyUrl);
×
455
        return appPrivacyPolicyUrl;
×
456
    }
457

458
    public boolean myDataDoesNotUsePermissionDocs() {
459
        boolean safeDefaultIfKeyNotFound = false;
×
460
        return settingsService.isTrueForKey(SettingsServiceBean.Key.MyDataDoesNotUseSolrPermissionDocs, safeDefaultIfKeyNotFound);
×
461
    }
462

463
    public boolean isFilesOnDatasetPageFromSolr() {
464
        boolean safeDefaultIfKeyNotFound = false;
×
465
        return settingsService.isTrueForKey(SettingsServiceBean.Key.FilesOnDatasetPageFromSolr, safeDefaultIfKeyNotFound);
×
466
    }
467

468
    public Long getMaxFileUploadSizeForStore(String driverId){
469
         return settingsService.getValueForCompoundKeyAsLong(SettingsServiceBean.Key.MaxFileUploadSizeInBytes, driverId);
×
470
     }
471
    
472
    public Integer getSearchHighlightFragmentSize() {
473
        String fragSize = settingsService.getValueForKey(SettingsServiceBean.Key.SearchHighlightFragmentSize);
×
474
        if (fragSize != null) {
×
475
            try {
476
                return new Integer(fragSize);
×
477
            } catch (NumberFormatException nfe) {
×
478
                logger.info("Could not convert " + SettingsServiceBean.Key.SearchHighlightFragmentSize + " to int: " + nfe);
×
479
            }
480
        }
481
        return null;
×
482
    }
483

484
    public long getTabularIngestSizeLimit() {
485
        // This method will return the blanket ingestable size limit, if 
486
        // set on the system. I.e., the universal limit that applies to all 
487
        // tabular ingests, regardless of fromat: 
488
        
489
        String limitEntry = settingsService.getValueForKey(SettingsServiceBean.Key.TabularIngestSizeLimit); 
×
490
        
491
        if (limitEntry != null) {
×
492
            try {
493
                Long sizeOption = new Long(limitEntry);
×
494
                return sizeOption;
×
495
            } catch (NumberFormatException nfe) {
×
496
                logger.warning("Invalid value for TabularIngestSizeLimit option? - " + limitEntry);
×
497
            }
498
        }
499
        // -1 means no limit is set; 
500
        // 0 on the other hand would mean that ingest is fully disabled for 
501
        // tabular data. 
502
        return -1; 
×
503
    }
504
    
505
    public long getTabularIngestSizeLimit(String formatName) {
506
        // This method returns the size limit set specifically for this format name,
507
        // if available, otherwise - the blanket limit that applies to all tabular 
508
        // ingests regardless of a format. 
509
        
510
        if (formatName == null || formatName.equals("")) {
×
511
            return getTabularIngestSizeLimit(); 
×
512
        }
513
        
514
        String limitEntry = settingsService.get(SettingsServiceBean.Key.TabularIngestSizeLimit.toString() + ":" + formatName); 
×
515
                
516
        if (limitEntry != null) {
×
517
            try {
518
                Long sizeOption = new Long(limitEntry);
×
519
                return sizeOption;
×
520
            } catch (NumberFormatException nfe) {
×
521
                logger.warning("Invalid value for TabularIngestSizeLimit:" + formatName + "? - " + limitEntry );
×
522
            }
523
        }
524
        
525
        return getTabularIngestSizeLimit();        
×
526
    }
527

528
    public boolean isOAIServerEnabled() {
529
        boolean defaultResponse = false;
×
530
        return settingsService.isTrueForKey(SettingsServiceBean.Key.OAIServerEnabled, defaultResponse);
×
531
    }
532
    
533
    public void enableOAIServer() {
534
        settingsService.setValueForKey(SettingsServiceBean.Key.OAIServerEnabled, "true");
×
535
    }
×
536
    
537
    public void disableOAIServer() {
538
        settingsService.deleteValueForKey(SettingsServiceBean.Key.OAIServerEnabled);
×
539
    }   
×
540
    
541
    public boolean isTimerServer() {
542
        String optionValue = System.getProperty(JVM_TIMER_SERVER_OPTION);
×
543
        if ("true".equalsIgnoreCase(optionValue)) {
×
544
            return true;
×
545
        }
546
        return false;
×
547
    }
548
    
549
    public String getFooterCopyrightAndYear() {
550
        return BundleUtil.getStringFromBundle("footer.copyright", Arrays.asList(Year.now().getValue() + ""));
×
551
    }
552

553
    public DataFile.ChecksumType getFileFixityChecksumAlgorithm() {
554
        DataFile.ChecksumType saneDefault = DataFile.ChecksumType.MD5;
×
555
        String checksumStringFromDatabase = settingsService.getValueForKey(SettingsServiceBean.Key.FileFixityChecksumAlgorithm, saneDefault.toString());
×
556
        try {
557
            DataFile.ChecksumType checksumTypeFromDatabase = DataFile.ChecksumType.fromString(checksumStringFromDatabase);
×
558
            return checksumTypeFromDatabase;
×
559
        } catch (IllegalArgumentException ex) {
×
560
            logger.info("The setting " + SettingsServiceBean.Key.FileFixityChecksumAlgorithm + " is misconfigured. " + ex.getMessage() + " Returning sane default: " + saneDefault + ".");
×
561
            return saneDefault;
×
562
        }
563
    }
564

565
    public String getDefaultAuthProvider() {
566
        String saneDefault = BuiltinAuthenticationProvider.PROVIDER_ID;
×
567
        String settingInDatabase = settingsService.getValueForKey(SettingsServiceBean.Key.DefaultAuthProvider, saneDefault);
×
568
        if (settingInDatabase != null && !settingInDatabase.isEmpty()) {
×
569
            /**
570
             * @todo Add more sanity checking.
571
             */
572
            return settingInDatabase;
×
573
        }
574
        return saneDefault;
×
575
    }
576

577
    public String getNameOfInstallation() {
578
        return dataverseService.getRootDataverseName();
×
579
    }
580

581
    public AbstractOAuth2AuthenticationProvider.DevOAuthAccountType getDevOAuthAccountType() {
582
        AbstractOAuth2AuthenticationProvider.DevOAuthAccountType saneDefault = AbstractOAuth2AuthenticationProvider.DevOAuthAccountType.PRODUCTION;
×
583
        String settingReturned = settingsService.getValueForKey(SettingsServiceBean.Key.DebugOAuthAccountType);
×
584
        logger.fine("setting returned: " + settingReturned);
×
585
        if (settingReturned != null) {
×
586
            try {
587
                AbstractOAuth2AuthenticationProvider.DevOAuthAccountType parsedValue = AbstractOAuth2AuthenticationProvider.DevOAuthAccountType.valueOf(settingReturned);
×
588
                return parsedValue;
×
589
            } catch (IllegalArgumentException ex) {
×
590
                logger.info("Couldn't parse value: " + ex + " - returning a sane default: " + saneDefault);
×
591
                return saneDefault;
×
592
            }
593
        } else {
594
            logger.fine("OAuth dev mode has not been configured. Returning a sane default: " + saneDefault);
×
595
            return saneDefault;
×
596
        }
597
    }
598

599
    public String getOAuth2CallbackUrl() {
600
        String saneDefault = getDataverseSiteUrl() + "/oauth2/callback.xhtml";
×
601
        String settingReturned = settingsService.getValueForKey(SettingsServiceBean.Key.OAuth2CallbackUrl);
×
602
        logger.fine("getOAuth2CallbackUrl setting returned: " + settingReturned);
×
603
        if (settingReturned != null) {
×
604
            return settingReturned;
×
605
        }
606
        return saneDefault;
×
607
    }
608
    
609
    public boolean isShibPassiveLoginEnabled() {
610
        boolean defaultResponse = false;
×
611
        return settingsService.isTrueForKey(SettingsServiceBean.Key.ShibPassiveLoginEnabled, defaultResponse);
×
612
    }
613
    public boolean isShibAttributeCharacterSetConversionEnabled() {
614
        boolean defaultResponse = true;
×
615
        return settingsService.isTrueForKey(SettingsServiceBean.Key.ShibAttributeCharacterSetConversionEnabled, defaultResponse);
×
616
    }
617

618
    /**
619
     * getPVDictionaries
620
     *
621
     * @return A string of one or more pipe (|) separated file paths.
622
     */
623
    public String getPVDictionaries() {
624
        return settingsService.get(SettingsServiceBean.Key.PVDictionaries.toString());
×
625
    }
626

627
    /**
628
     * getPVGoodStrength
629
     *
630
     * Get the minimum length of a valid password to apply an expiration rule.
631
     * Defaults to 20.
632
     *
633
     * @return The length.
634
     */
635
    public int getPVGoodStrength() {
636
        // FIXME: Change this to 21 to match Harvard's requirements or implement a way to disable the rule (0 or -1) and have the default be disabled.
637
        int goodStrengthLength = 20;
×
638
        //String _goodStrengthLength = System.getProperty("pv.goodstrength", settingsService.get(SettingsServiceBean.Key.PVGoodStrength.toString()));
639
        String _goodStrengthLength = settingsService.get(SettingsServiceBean.Key.PVGoodStrength.toString());
×
640
        try {
641
            goodStrengthLength = Integer.parseInt(_goodStrengthLength);
×
642
        } catch (NumberFormatException nfe) {
×
643
            logger.fine("Invalid value for PVGoodStrength: " + _goodStrengthLength);
×
644
        }
×
645
        return goodStrengthLength;
×
646
    }
647

648
    /**
649
     * getPVMinLength
650
     *
651
     * Get the minimum length of a valid password. Defaults to 6.
652
     *
653
     * @return The length.
654
     */
655
    public int getPVMinLength() {
656
        int passportValidatorMinLength = 6;
×
657
        String _passportValidatorMinLength = settingsService.get(SettingsServiceBean.Key.PVMinLength.toString());
×
658
        try {
659
            passportValidatorMinLength = Integer.parseInt(_passportValidatorMinLength);
×
660
        } catch (NumberFormatException nfe) {
×
661
            logger.fine("Invalid value for PwMinLength: " + _passportValidatorMinLength);
×
662
        }
×
663
        return passportValidatorMinLength;
×
664
    }
665

666
    /**
667
     * getPVMaxLength
668
     *
669
     * Get the maximum length of a valid password. Defaults to 0 (disabled).
670
     *
671
     * @return The length.
672
     */
673
    public int getPVMaxLength() {
674
        int passportValidatorMaxLength = 0;
×
675
        String _passportValidatorMaxLength = settingsService.get(SettingsServiceBean.Key.PVMaxLength.toString());
×
676
        try {
677
            passportValidatorMaxLength = Integer.parseInt(_passportValidatorMaxLength);
×
678
        } catch (NumberFormatException nfe) {
×
679
            logger.fine("Invalid value for PwMaxLength: " + _passportValidatorMaxLength);
×
680
        }
×
681
        return passportValidatorMaxLength;
×
682
    }
683

684
    /**
685
     * One letter, 2 special characters, etc. Defaults to:
686
     *
687
     * - one uppercase
688
     *
689
     * - one lowercase
690
     *
691
     * - one digit
692
     *
693
     * - one special character
694
     *
695
     * TODO: This is more strict than what Dataverse 4.0 shipped with. Consider
696
     * keeping the default the same.
697
     */
698
    public List<CharacterRule> getPVCharacterRules() {
699
        String characterRulesString = settingsService.get(SettingsServiceBean.Key.PVCharacterRules.toString());
×
700
        return PasswordValidatorUtil.getCharacterRules(characterRulesString);
×
701
    }
702

703
    /**
704
     * getPVNumberOfCharacteristics
705
     *
706
     * Get the number M characteristics. Defaults to 3.
707
     *
708
     * @return The number.
709
     * 
710
     * TODO: Consider changing the out-of-the-box rules to be the same as Dataverse 4.0, which was 2 (one letter, one number).
711
     */
712
    public int getPVNumberOfCharacteristics() {
713
        int numberOfCharacteristics = 2;
×
714
        String _numberOfCharacteristics = settingsService.get(SettingsServiceBean.Key.PVNumberOfCharacteristics.toString());
×
715
        try {
716
            numberOfCharacteristics = Integer.parseInt(_numberOfCharacteristics);
×
717
        } catch (NumberFormatException nfe) {
×
718
            logger.fine("Invalid value for PVNumberOfCharacteristics: " + _numberOfCharacteristics);
×
719
        }
×
720
        return numberOfCharacteristics;
×
721
    }
722

723
    /**
724
     * Get the number of consecutive digits allowed. Defaults to highest int
725
     * possible.
726
     */
727
    public int getPVNumberOfConsecutiveDigitsAllowed() {
728
        int numConsecutiveDigitsAllowed = Integer.MAX_VALUE;
×
729
        String _numberOfConsecutiveDigitsAllowed = settingsService.get(SettingsServiceBean.Key.PVNumberOfConsecutiveDigitsAllowed.toString());
×
730
        try {
731
            numConsecutiveDigitsAllowed = Integer.parseInt(_numberOfConsecutiveDigitsAllowed);
×
732
        } catch (NumberFormatException nfe) {
×
733
            logger.fine("Invalid value for " + SettingsServiceBean.Key.PVNumberOfConsecutiveDigitsAllowed + ": " + _numberOfConsecutiveDigitsAllowed);
×
734
        }
×
735
        return numConsecutiveDigitsAllowed;
×
736
    }
737

738
    /**
739
     * Below are three related enums having to do with big data support:
740
     *
741
     * - FileUploadMethods
742
     *
743
     * - FileDownloadMethods
744
     *
745
     * - TransferProtocols
746
     *
747
     * There is a good chance these will be consolidated in the future.
748
     */
749
    public enum FileUploadMethods {
1✔
750

751
        /**
752
         * DCM stands for Data Capture Module. Right now it supports upload over
753
         * rsync+ssh but DCM may support additional methods in the future.
754
         */
755
        @Deprecated(forRemoval = true, since = "2024-07-07")
1✔
756
        RSYNC("dcm/rsync+ssh"),
757
        /**
758
         * Traditional Dataverse file handling, which tends to involve users
759
         * uploading and downloading files using a browser or APIs.
760
         */
761
        NATIVE("native/http"),
1✔
762

763
        /**
764
         * Upload through Globus of large files
765
         */
766

767
        GLOBUS("globus"), 
1✔
768
        
769
        /**
770
         * Upload folders of files through dvwebloader app
771
         */
772

773
        WEBLOADER("dvwebloader");
1✔
774
        ;
775

776

777
        private final String text;
778

779
        private FileUploadMethods(final String text) {
1✔
780
            this.text = text;
1✔
781
        }
1✔
782

783
        public static FileUploadMethods fromString(String text) {
784
            if (text != null) {
×
785
                for (FileUploadMethods fileUploadMethods : FileUploadMethods.values()) {
×
786
                    if (text.equals(fileUploadMethods.text)) {
×
787
                        return fileUploadMethods;
×
788
                    }
789
                }
790
            }
791
            throw new IllegalArgumentException("FileUploadMethods must be one of these values: " + Arrays.asList(FileUploadMethods.values()) + ".");
×
792
        }
793

794
        @Override
795
        public String toString() {
796
            return text;
1✔
797
        }
798
        
799
        
800
    }
801

802
    /**
803
     * See FileUploadMethods.
804
     *
805
     * TODO: Consider if dataverse.files.<id>.download-redirect belongs here since
806
     * it's a way to bypass Glassfish when downloading.
807
     */
808
    public enum FileDownloadMethods {
×
809
        /**
810
         * RSAL stands for Repository Storage Abstraction Layer. Downloads don't
811
         * go through Glassfish.
812
         */
813
        @Deprecated(forRemoval = true, since = "2024-07-07")
×
814
        RSYNC("rsal/rsync"),
815
        NATIVE("native/http"),
×
816
        GLOBUS("globus")
×
817
        ;
818
        private final String text;
819

820
        private FileDownloadMethods(final String text) {
×
821
            this.text = text;
×
822
        }
×
823

824
        public static FileUploadMethods fromString(String text) {
825
            if (text != null) {
×
826
                for (FileUploadMethods fileUploadMethods : FileUploadMethods.values()) {
×
827
                    if (text.equals(fileUploadMethods.text)) {
×
828
                        return fileUploadMethods;
×
829
                    }
830
                }
831
            }
832
            throw new IllegalArgumentException("FileDownloadMethods must be one of these values: " + Arrays.asList(FileDownloadMethods.values()) + ".");
×
833
        }
834

835
        @Override
836
        public String toString() {
837
            return text;
×
838
        }
839
        
840
    }
841
    
842
    public enum DataFilePIDFormat {
1✔
843
        DEPENDENT("DEPENDENT"),
1✔
844
        INDEPENDENT("INDEPENDENT");
1✔
845
        private final String text;
846

847
        public String getText() {
848
            return text;
×
849
        }
850
        
851
        private DataFilePIDFormat(final String text){
1✔
852
            this.text = text;
1✔
853
        }
1✔
854
        
855
        @Override
856
        public String toString() {
857
            return text;
1✔
858
        }
859
        
860
    }
861

862
    /**
863
     * See FileUploadMethods.
864
     */
865
    public enum TransferProtocols {
1✔
866

867
        @Deprecated(forRemoval = true, since = "2024-07-07")
1✔
868
        RSYNC("rsync"),
869
        /**
870
         * POSIX includes NFS. This is related to Key.LocalDataAccessPath in
871
         * SettingsServiceBean.
872
         */
873
        POSIX("posix"),
1✔
874
        GLOBUS("globus");
1✔
875

876
        private final String text;
877

878
        private TransferProtocols(final String text) {
1✔
879
            this.text = text;
1✔
880
        }
1✔
881

882
        public static TransferProtocols fromString(String text) {
883
            if (text != null) {
1✔
884
                for (TransferProtocols transferProtocols : TransferProtocols.values()) {
1✔
885
                    if (text.equals(transferProtocols.text)) {
1✔
886
                        return transferProtocols;
1✔
887
                    }
888
                }
889
            }
890
            throw new IllegalArgumentException("TransferProtocols must be one of these values: " + Arrays.asList(TransferProtocols.values()) + ".");
1✔
891
        }
892

893
        @Override
894
        public String toString() {
895
            return text;
1✔
896
        }
897

898
    }
899
    
900
    public boolean isPublicInstall(){
901
        boolean saneDefault = false;
×
902
        return settingsService.isTrueForKey(SettingsServiceBean.Key.PublicInstall, saneDefault);
×
903
    }
904

905
    @Deprecated(forRemoval = true, since = "2024-07-07")
906
    public boolean isRsyncUpload(){
907
        return getMethodAvailable(SystemConfig.FileUploadMethods.RSYNC.toString(), true);
×
908
    }
909

910
    public boolean isGlobusUpload(){
911
        return getMethodAvailable(FileUploadMethods.GLOBUS.toString(), true);
×
912
    }
913
    
914
    public boolean isWebloaderUpload(){
915
        return getMethodAvailable(FileUploadMethods.WEBLOADER.toString(), true);
×
916
    }
917

918
    // Controls if HTTP upload is enabled for both GUI and API.
919
    public boolean isHTTPUpload(){       
920
        return getMethodAvailable(SystemConfig.FileUploadMethods.NATIVE.toString(), true);
×
921
    }
922

923
    @Deprecated(forRemoval = true, since = "2024-07-07")
924
    public boolean isRsyncOnly(){
925
        String downloadMethods = settingsService.getValueForKey(SettingsServiceBean.Key.DownloadMethods);
×
926
        if(downloadMethods == null){
×
927
            return false;
×
928
        }
929
        if (!downloadMethods.toLowerCase().equals(SystemConfig.FileDownloadMethods.RSYNC.toString())){
×
930
            return false;
×
931
        }
932
        String uploadMethods = settingsService.getValueForKey(SettingsServiceBean.Key.UploadMethods);
×
933
        if (uploadMethods==null){
×
934
            return false;
×
935
        } else {
936
           return  Arrays.asList(uploadMethods.toLowerCase().split("\\s*,\\s*")).size() == 1 && uploadMethods.toLowerCase().equals(SystemConfig.FileUploadMethods.RSYNC.toString());
×
937
        }
938
    }
939

940
    @Deprecated(forRemoval = true, since = "2024-07-07")
941
    public boolean isRsyncDownload() {
942
        return getMethodAvailable(SystemConfig.FileUploadMethods.RSYNC.toString(), false);
×
943
    }
944

945
    public boolean isHTTPDownload() {
946
        return getMethodAvailable(SystemConfig.FileUploadMethods.NATIVE.toString(), false);
×
947
    }
948

949
    public boolean isGlobusDownload() {
950
        return getMethodAvailable(FileDownloadMethods.GLOBUS.toString(), false);
×
951
    }
952
    
953
    public boolean isGlobusFileDownload() {
954
        return (isGlobusDownload() && settingsService.isTrueForKey(SettingsServiceBean.Key.GlobusSingleFileTransfer, false));
×
955
    }
956

957
    private Boolean getMethodAvailable(String method, boolean upload) {
958
        String methods = settingsService.getValueForKey(
×
959
                upload ? SettingsServiceBean.Key.UploadMethods : SettingsServiceBean.Key.DownloadMethods);
×
960
        if (methods == null) {
×
961
            return false;
×
962
        } else {
963
            return Arrays.asList(methods.toLowerCase().split("\\s*,\\s*")).contains(method);
×
964
        }
965
    }
966
    
967
    public Integer getUploadMethodCount(){
968
        String uploadMethods = settingsService.getValueForKey(SettingsServiceBean.Key.UploadMethods); 
×
969
        if (uploadMethods==null){
×
970
            return 0;
×
971
        } else {
972
           return  Arrays.asList(uploadMethods.toLowerCase().split("\\s*,\\s*")).size();
×
973
        }       
974
    }
975

976
    public boolean isAllowCustomTerms() {
977
        boolean safeDefaultIfKeyNotFound = true;
×
978
        return settingsService.isTrueForKey(SettingsServiceBean.Key.AllowCustomTermsOfUse, safeDefaultIfKeyNotFound);
×
979
    }
980

981
    public boolean isFilePIDsEnabledForCollection(Dataverse collection) {
982
        if (collection == null) {
×
983
            return false;
×
984
        }
985
        
986
        Dataverse thisCollection = collection; 
×
987
        
988
        // If neither enabled nor disabled specifically for this collection,
989
        // the parent collection setting is inhereted (recursively): 
990
        while (thisCollection.getFilePIDsEnabled() == null) {
×
991
            if (thisCollection.getOwner() == null) {
×
992
                // We've reached the root collection, and file PIDs registration
993
                // hasn't been explicitly enabled, therefore we presume that it is
994
                // subject to how the registration is configured for the 
995
                // entire instance:
996
                return settingsService.isTrueForKey(SettingsServiceBean.Key.FilePIDsEnabled, false); 
×
997
            }
998
            thisCollection = thisCollection.getOwner();
×
999
        }
1000
        
1001
        // If present, the setting of the first direct ancestor collection 
1002
        // takes precedent:
1003
        return thisCollection.getFilePIDsEnabled();
×
1004
    }
1005
    
1006

1007

1008
    public String getMDCLogPath() {
UNCOV
1009
        String mDCLogPath = settingsService.getValueForKey(SettingsServiceBean.Key.MDCLogPath, null);
×
UNCOV
1010
        return mDCLogPath;
×
1011
    }
1012
    
1013
    public boolean isDatafileValidationOnPublishEnabled() {
UNCOV
1014
        boolean safeDefaultIfKeyNotFound = true;
×
UNCOV
1015
        return settingsService.isTrueForKey(SettingsServiceBean.Key.FileValidationOnPublishEnabled, safeDefaultIfKeyNotFound);
×
1016
    }
1017

1018
        public boolean directUploadEnabled(DvObjectContainer container) {
UNCOV
1019
            return Boolean.getBoolean("dataverse.files." + container.getEffectiveStorageDriverId() + ".upload-redirect");
×
1020
        }
1021
        
1022
    public boolean isExternalDataverseValidationEnabled() {
UNCOV
1023
        return settingsService.getValueForKey(SettingsServiceBean.Key.DataverseMetadataValidatorScript) != null;
×
1024
        // alternatively, we can also check if the script specified exists, 
1025
        // and is executable. -- ?
1026
    }
1027
    
1028
    public boolean isExternalDatasetValidationEnabled() {
UNCOV
1029
        return settingsService.getValueForKey(SettingsServiceBean.Key.DatasetMetadataValidatorScript) != null;
×
1030
        // alternatively, we can also check if the script specified exists, 
1031
        // and is executable. -- ?
1032
    }
1033
    
1034
    public String getDataverseValidationExecutable() {
UNCOV
1035
        return settingsService.getValueForKey(SettingsServiceBean.Key.DataverseMetadataValidatorScript);
×
1036
    }
1037
    
1038
    public String getDatasetValidationExecutable() {
UNCOV
1039
        return settingsService.getValueForKey(SettingsServiceBean.Key.DatasetMetadataValidatorScript);
×
1040
    }
1041
    
1042
    public String getDataverseValidationFailureMsg() {
UNCOV
1043
        String defaultMessage = "This dataverse collection cannot be published because it has failed an external metadata validation test.";
×
UNCOV
1044
        return settingsService.getValueForKey(SettingsServiceBean.Key.DataverseMetadataPublishValidationFailureMsg, defaultMessage);
×
1045
    }
1046
    
1047
    public String getDataverseUpdateValidationFailureMsg() {
UNCOV
1048
        String defaultMessage = "This dataverse collection cannot be updated because it has failed an external metadata validation test.";
×
UNCOV
1049
        return settingsService.getValueForKey(SettingsServiceBean.Key.DataverseMetadataUpdateValidationFailureMsg, defaultMessage);
×
1050
    }
1051
    
1052
    public String getDatasetValidationFailureMsg() {
UNCOV
1053
        String defaultMessage = "This dataset cannot be published because it has failed an external metadata validation test.";
×
UNCOV
1054
        return settingsService.getValueForKey(SettingsServiceBean.Key.DatasetMetadataValidationFailureMsg, defaultMessage);
×
1055
    }
1056
    
1057
    public boolean isExternalValidationAdminOverrideEnabled() {
UNCOV
1058
        return "true".equalsIgnoreCase(settingsService.getValueForKey(SettingsServiceBean.Key.ExternalValidationAdminOverride));
×
1059
    }
1060
    
1061
    public long getDatasetValidationSizeLimit() {
1062
        String limitEntry = settingsService.getValueForKey(SettingsServiceBean.Key.DatasetChecksumValidationSizeLimit);
×
1063

1064
        if (limitEntry != null) {
×
1065
            try {
1066
                Long sizeOption = new Long(limitEntry);
×
1067
                return sizeOption;
×
UNCOV
1068
            } catch (NumberFormatException nfe) {
×
UNCOV
1069
                logger.warning("Invalid value for DatasetValidationSizeLimit option? - " + limitEntry);
×
1070
            }
1071
        }
1072
        // -1 means no limit is set;
UNCOV
1073
        return -1;
×
1074
    }
1075

1076
    public long getFileValidationSizeLimit() {
1077
        String limitEntry = settingsService.getValueForKey(SettingsServiceBean.Key.DataFileChecksumValidationSizeLimit);
×
1078

1079
        if (limitEntry != null) {
×
1080
            try {
1081
                Long sizeOption = new Long(limitEntry);
×
1082
                return sizeOption;
×
UNCOV
1083
            } catch (NumberFormatException nfe) {
×
UNCOV
1084
                logger.warning("Invalid value for FileValidationSizeLimit option? - " + limitEntry);
×
1085
            }
1086
        }
1087
        // -1 means no limit is set;
UNCOV
1088
        return -1;
×
1089
    }
1090
    public Map<String, String[]> getCurationLabels() {
1091
        Map<String, String[]> labelMap = new HashMap<String, String[]>();
×
1092
        String setting = settingsService.getValueForKey(SettingsServiceBean.Key.AllowedCurationLabels, "");
×
UNCOV
1093
        if (!setting.isEmpty()) {
×
1094
            try (JsonReader jsonReader = Json.createReader(new StringReader(setting))){
×
1095
                
1096
                Pattern pattern = Pattern.compile("(^[\\w ]+$)"); // alphanumeric, underscore and whitespace allowed
×
1097

1098
                JsonObject labelSets = jsonReader.readObject();
×
1099
                for (String key : labelSets.keySet()) {
×
UNCOV
1100
                    JsonArray labels = (JsonArray) labelSets.getJsonArray(key);
×
1101
                    String[] labelArray = new String[labels.size()];
×
1102

1103
                    boolean allLabelsOK = true;
×
1104
                    Iterator<JsonValue> iter = labels.iterator();
×
1105
                    int i = 0;
×
1106
                    while (iter.hasNext()) {
×
1107
                        String label = ((JsonString) iter.next()).getString();
×
1108
                        Matcher matcher = pattern.matcher(label);
×
1109
                        if (!matcher.matches()) {
×
1110
                            logger.warning("Label rejected: " + label + ", Label set " + key + " ignored.");
×
UNCOV
1111
                            allLabelsOK = false;
×
1112
                            break;
×
1113
                        }
1114
                        labelArray[i] = label;
×
1115
                        i++;
×
1116
                    }
×
UNCOV
1117
                    if (allLabelsOK) {
×
1118
                        labelMap.put(key, labelArray);
×
1119
                    }
1120
                }
×
1121
            } catch (Exception e) {
×
1122
                logger.warning("Unable to parse " + SettingsServiceBean.Key.AllowedCurationLabels.name() + ": "
×
1123
                        + e.getLocalizedMessage());
×
UNCOV
1124
                e.printStackTrace();
×
1125
            }
×
1126
        }
UNCOV
1127
        return labelMap;
×
1128
    }
1129
    
1130
    public boolean isSignupDisabledForRemoteAuthProvider(String providerId) {
UNCOV
1131
        Boolean ret =  settingsService.getValueForCompoundKeyAsBoolean(SettingsServiceBean.Key.AllowRemoteAuthSignUp, providerId);
×
1132
        
1133
        // we default to false - i.e., "not disabled" if the setting is not present: 
UNCOV
1134
        if (ret == null) {
×
UNCOV
1135
            return false; 
×
1136
        }
1137
        
UNCOV
1138
        return !ret; 
×
1139
    }
1140
    
1141
    public boolean isStorageQuotasEnforced() {
UNCOV
1142
        return settingsService.isTrueForKey(SettingsServiceBean.Key.UseStorageQuotas, false);
×
1143
    }
1144
    
1145
    /**
1146
     * This method should only be used for testing of the new storage quota 
1147
     * mechanism, temporarily. (it uses the same value as the quota for 
1148
     * *everybody* regardless of the circumstances, defined as a database 
1149
     * setting)
1150
     */
1151
    public Long getTestStorageQuotaLimit() {
UNCOV
1152
        return settingsService.getValueForKeyAsLong(SettingsServiceBean.Key.StorageQuotaSizeInBytes);
×
1153
    }
1154
    /**
1155
     * Should we store tab-delimited files produced during ingest *with* the
1156
     * variable name header line included?
1157
     * @return boolean - defaults to false.
1158
     */
1159
    public boolean isStoringIngestedFilesWithHeaders() {
UNCOV
1160
        return settingsService.isTrueForKey(SettingsServiceBean.Key.StoreIngestedTabularFilesWithVarHeaders, false);
×
1161
    }
1162

1163
    /**
1164
     * RateLimitUtil will parse the json to create a List<RateLimitSetting>
1165
     */
1166
    public String getRateLimitsJson() {
UNCOV
1167
        return settingsService.getValueForKey(SettingsServiceBean.Key.RateLimitingCapacityByTierAndAction, "");
×
1168
    }
1169
    public String getRateLimitingDefaultCapacityTiers() {
UNCOV
1170
        return settingsService.getValueForKey(SettingsServiceBean.Key.RateLimitingDefaultCapacityTiers, "");
×
1171
    }
1172
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc