/* * decaffeinate suggestions: * DS205: Consider reworking code to avoid use of IIFEs * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ let allTexLiveDockerImageNames, allTexLiveDockerImages, redisConfig, siteUrl; let e; const Path = require('path'); // These credentials are used for authenticating api requests // between services that may need to go over public channels const httpAuthUser = "sharelatex"; const httpAuthPass = process.env["WEB_API_PASSWORD"]; const httpAuthUsers = {}; httpAuthUsers[httpAuthUser] = httpAuthPass; const parse = function(option){ if (option != null) { try { const opt = JSON.parse(option); return opt; } catch (err) { throw new Error(`problem parsing ${option}, invalid JSON`); } } }; const parseIntOrFail = function(value){ const parsedValue = parseInt(value, 10); if (isNaN(parsedValue)) { throw new Error(`'${value}' is an invalid integer`); } return parsedValue; }; const DATA_DIR = '/var/lib/sharelatex/data'; const TMP_DIR = '/var/lib/sharelatex/tmp'; const settings = { clsi: { optimiseInDocker: process.env['OPTIMISE_PDF'] === 'true' }, brandPrefix: "", allowAnonymousReadAndWriteSharing: process.env['SHARELATEX_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING'] === 'true', // Databases // --------- // ShareLaTeX's main persistent data store is MongoDB (http://www.mongodb.org/) // Documentation about the URL connection string format can be found at: // // http://docs.mongodb.org/manual/reference/connection-string/ // // The following works out of the box with Mongo's default settings: mongo: { url : process.env["SHARELATEX_MONGO_URL"] || 'mongodb://dockerhost/sharelatex' }, // Redis is used in ShareLaTeX for high volume queries, like real-time // editing, and session management. // // The following config will work with Redis's default settings: redis: { web: (redisConfig = { host: process.env["SHARELATEX_REDIS_HOST"] || "dockerhost", port: process.env["SHARELATEX_REDIS_PORT"] || "6379", password: process.env["SHARELATEX_REDIS_PASS"] || undefined, key_schema: { // document-updater blockingKey({doc_id}) { return `Blocking:${doc_id}`; }, docLines({doc_id}) { return `doclines:${doc_id}`; }, docOps({doc_id}) { return `DocOps:${doc_id}`; }, docVersion({doc_id}) { return `DocVersion:${doc_id}`; }, docHash({doc_id}) { return `DocHash:${doc_id}`; }, projectKey({doc_id}) { return `ProjectId:${doc_id}`; }, docsInProject({project_id}) { return `DocsIn:${project_id}`; }, ranges({doc_id}) { return `Ranges:${doc_id}`; }, // document-updater:realtime pendingUpdates({doc_id}) { return `PendingUpdates:${doc_id}`; }, // document-updater:history uncompressedHistoryOps({doc_id}) { return `UncompressedHistoryOps:${doc_id}`; }, docsWithHistoryOps({project_id}) { return `DocsWithHistoryOps:${project_id}`; }, // document-updater:lock blockingKey({doc_id}) { return `Blocking:${doc_id}`; }, // track-changes:lock historyLock({doc_id}) { return `HistoryLock:${doc_id}`; }, historyIndexLock({project_id}) { return `HistoryIndexLock:${project_id}`; }, // track-changes:history uncompressedHistoryOps({doc_id}) { return `UncompressedHistoryOps:${doc_id}`; }, docsWithHistoryOps({project_id}) { return `DocsWithHistoryOps:${project_id}`; }, // realtime clientsInProject({project_id}) { return `clients_in_project:${project_id}`; }, connectedUser({project_id, client_id}){ return `connected_user:${project_id}:${client_id}`; } } }), fairy: redisConfig, // track-changes and document-updater realtime: redisConfig, documentupdater: redisConfig, lock: redisConfig, history: redisConfig, websessions: redisConfig, api: redisConfig, pubsub: redisConfig, project_history: redisConfig }, // The compile server (the clsi) uses a SQL database to cache files and // meta-data. sqlite is the default, and the load is low enough that this will // be fine in production (we use sqlite at sharelatex.com). // // If you want to configure a different database, see the Sequelize documentation // for available options: // // https://github.com/sequelize/sequelize/wiki/API-Reference-Sequelize#example-usage // mysql: { clsi: { database: "clsi", username: "clsi", password: "", dialect: "sqlite", storage: Path.join(DATA_DIR, "db.sqlite") } }, // File storage // ------------ // ShareLaTeX can store binary files like images either locally or in Amazon // S3. The default is locally: filestore: { backend: "fs", stores: { user_files: Path.join(DATA_DIR, "user_files"), template_files: Path.join(DATA_DIR, "template_files") } }, // To use Amazon S3 as a storage backend, comment out the above config, and // uncomment the following, filling in your key, secret, and bucket name: // // filestore: // backend: "s3" // stores: // user_files: "BUCKET_NAME" // s3: // key: "AWS_KEY" // secret: "AWS_SECRET" // trackchanges: { continueOnError: true }, // Local disk caching // ------------------ path: { // If we ever need to write something to disk (e.g. incoming requests // that need processing but may be too big for memory), then write // them to disk here: dumpFolder: Path.join(TMP_DIR, "dumpFolder"), // Where to write uploads before they are processed uploadFolder: Path.join(TMP_DIR, "uploads"), // Where to write the project to disk before running LaTeX on it compilesDir: Path.join(DATA_DIR, "compiles"), // Where to cache downloaded URLs for the CLSI clsiCacheDir: Path.join(DATA_DIR, "cache"), // Where to write the output files to disk after running LaTeX outputDir: Path.join(DATA_DIR, "output") }, // Server Config // ------------- // Where your instance of ShareLaTeX can be found publicly. This is used // when emails are sent out and in generated links: siteUrl: (siteUrl = process.env["SHARELATEX_SITE_URL"] || 'http://localhost'), // The name this is used to describe your ShareLaTeX Installation appName: process.env["SHARELATEX_APP_NAME"] || "ShareLaTeX (Community Edition)", restrictInvitesToExistingAccounts: process.env["SHARELATEX_RESTRICT_INVITES_TO_EXISTING_ACCOUNTS"] === 'true', nav: { title: process.env["SHARELATEX_NAV_TITLE"] || process.env["SHARELATEX_APP_NAME"] || "ShareLaTeX Community Edition" }, // The email address which users will be directed to as the main point of // contact for this installation of ShareLaTeX. adminEmail: process.env["SHARELATEX_ADMIN_EMAIL"] || "placeholder@example.com", // If provided, a sessionSecret is used to sign cookies so that they cannot be // spoofed. This is recommended. security: { sessionSecret: process.env["SHARELATEX_SESSION_SECRET"] || process.env["CRYPTO_RANDOM"] }, // These credentials are used for authenticating api requests // between services that may need to go over public channels httpAuthUsers, // Should javascript assets be served minified or not. useMinifiedJs: true, // Should static assets be sent with a header to tell the browser to cache // them. This should be false in development where changes are being made, // but should be set to true in production. cacheStaticAssets: true, // If you are running ShareLaTeX over https, set this to true to send the // cookie with a secure flag (recommended). secureCookie: (process.env["SHARELATEX_SECURE_COOKIE"] != null), // If you are running ShareLaTeX behind a proxy (like Apache, Nginx, etc) // then set this to true to allow it to correctly detect the forwarded IP // address and http/https protocol information. behindProxy: process.env["SHARELATEX_BEHIND_PROXY"] || false, i18n: { subdomainLang: { www: {lngCode:process.env["SHARELATEX_SITE_LANGUAGE"] || "en", url: siteUrl} }, defaultLng: process.env["SHARELATEX_SITE_LANGUAGE"] || "en" }, currentImageName: process.env["TEX_LIVE_DOCKER_IMAGE"], apis: { web: { url: "http://localhost:3000", user: httpAuthUser, pass: httpAuthPass }, project_history: { enabled: false } }, references:{}, notifications:undefined, defaultFeatures: { collaborators: -1, dropbox: true, versioning: true, compileTimeout: parseIntOrFail(process.env["COMPILE_TIMEOUT"] || 180), compileGroup: "standard", trackChanges: true, templates: true, references: true } }; //# OPTIONAL CONFIGURABLE SETTINGS if (process.env["SHARELATEX_LEFT_FOOTER"] != null) { try { settings.nav.left_footer = JSON.parse(process.env["SHARELATEX_LEFT_FOOTER"]); } catch (error) { e = error; console.error("could not parse SHARELATEX_LEFT_FOOTER, not valid JSON"); } } if (process.env["SHARELATEX_RIGHT_FOOTER"] != null) { settings.nav.right_footer = process.env["SHARELATEX_RIGHT_FOOTER"]; try { settings.nav.right_footer = JSON.parse(process.env["SHARELATEX_RIGHT_FOOTER"]); } catch (error1) { e = error1; console.error("could not parse SHARELATEX_RIGHT_FOOTER, not valid JSON"); } } if (process.env["SHARELATEX_HEADER_IMAGE_URL"] != null) { settings.nav.custom_logo = process.env["SHARELATEX_HEADER_IMAGE_URL"]; } if (process.env["SHARELATEX_HEADER_NAV_LINKS"] != null) { console.error(`\ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # WARNING: SHARELATEX_HEADER_NAV_LINKS is no longer supported # See https://github.com/sharelatex/sharelatex/wiki/Configuring-Headers,-Footers-&-Logo # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\ ` ); } if (process.env["SHARELATEX_HEADER_EXTRAS"] != null) { try { settings.nav.header_extras = JSON.parse(process.env["SHARELATEX_HEADER_EXTRAS"]); } catch (error2) { e = error2; console.error("could not parse SHARELATEX_HEADER_EXTRAS, not valid JSON"); } } // Sending Email // ------------- // // You must configure a mail server to be able to send invite emails from // ShareLaTeX. The config settings are passed to nodemailer. See the nodemailer // documentation for available options: // // http://www.nodemailer.com/docs/transports if (process.env["SHARELATEX_EMAIL_FROM_ADDRESS"] != null) { settings.email = { fromAddress: process.env["SHARELATEX_EMAIL_FROM_ADDRESS"], replyTo: process.env["SHARELATEX_EMAIL_REPLY_TO"] || "", driver: process.env["SHARELATEX_EMAIL_DRIVER"], parameters: { //AWS Creds AWSAccessKeyID: process.env["SHARELATEX_EMAIL_AWS_SES_ACCESS_KEY_ID"], AWSSecretKey: process.env["SHARELATEX_EMAIL_AWS_SES_SECRET_KEY"], //SMTP Creds host: process.env["SHARELATEX_EMAIL_SMTP_HOST"], port: process.env["SHARELATEX_EMAIL_SMTP_PORT"], secure: parse(process.env["SHARELATEX_EMAIL_SMTP_SECURE"]), ignoreTLS: parse(process.env["SHARELATEX_EMAIL_SMTP_IGNORE_TLS"]), name: process.env["SHARELATEX_EMAIL_SMTP_NAME"], logger: process.env["SHARELATEX_EMAIL_SMTP_LOGGER"] === 'true' }, textEncoding: process.env["SHARELATEX_EMAIL_TEXT_ENCODING"], template: { customFooter: process.env["SHARELATEX_CUSTOM_EMAIL_FOOTER"] } }; if (process.env["SHARELATEX_EMAIL_AWS_SES_REGION"] != null) { settings.email.parameters.region = process.env["SHARELATEX_EMAIL_AWS_SES_REGION"]; } if ((process.env["SHARELATEX_EMAIL_SMTP_USER"] != null) || (process.env["SHARELATEX_EMAIL_SMTP_PASS"] != null)) { settings.email.parameters.auth = { user: process.env["SHARELATEX_EMAIL_SMTP_USER"], pass: process.env["SHARELATEX_EMAIL_SMTP_PASS"] }; } if (process.env["SHARELATEX_EMAIL_SMTP_TLS_REJECT_UNAUTH"] != null) { settings.email.parameters.tls = {rejectUnauthorized: parse(process.env["SHARELATEX_EMAIL_SMTP_TLS_REJECT_UNAUTH"])}; } } // i18n if (process.env["SHARELATEX_LANG_DOMAIN_MAPPING"] != null) { settings.i18n.subdomainLang = parse(process.env["SHARELATEX_LANG_DOMAIN_MAPPING"]); } // Password Settings // ----------- // These restrict the passwords users can use when registering // opts are from http://antelle.github.io/passfield if (process.env["SHARELATEX_PASSWORD_VALIDATION_PATTERN"] || process.env["SHARELATEX_PASSWORD_VALIDATION_MIN_LENGTH"] || process.env["SHARELATEX_PASSWORD_VALIDATION_MAX_LENGTH"]) { settings.passwordStrengthOptions = { pattern: process.env["SHARELATEX_PASSWORD_VALIDATION_PATTERN"] || "aA$3", length: {min:process.env["SHARELATEX_PASSWORD_VALIDATION_MIN_LENGTH"] || 8, max: process.env["SHARELATEX_PASSWORD_VALIDATION_MAX_LENGTH"] || 150} }; } //###################### // ShareLaTeX Server Pro //###################### if (parse(process.env["SHARELATEX_IS_SERVER_PRO"]) === true) { settings.bypassPercentageRollouts = true; settings.apis.references = {url: "http://localhost:3040"}; } // LDAP - SERVER PRO ONLY // ---------- if (process.env["SHARELATEX_LDAP_HOST"]) { console.error(`\ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # WARNING: The LDAP configuration format has changed in version 0.5.1 # See https://github.com/sharelatex/sharelatex/wiki/Server-Pro:-LDAP-Config # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\ ` ); } if (process.env["SHARELATEX_LDAP_URL"]) { let _ldap_connect_timeout, _ldap_group_search_attribs, _ldap_search_attribs, _ldap_timeout; settings.externalAuth = true; settings.ldap = { emailAtt: process.env["SHARELATEX_LDAP_EMAIL_ATT"], nameAtt: process.env["SHARELATEX_LDAP_NAME_ATT"], lastNameAtt: process.env["SHARELATEX_LDAP_LAST_NAME_ATT"], updateUserDetailsOnLogin: process.env["SHARELATEX_LDAP_UPDATE_USER_DETAILS_ON_LOGIN"] === 'true', placeholder: process.env["SHARELATEX_LDAP_PLACEHOLDER"], server: { url: process.env["SHARELATEX_LDAP_URL"], bindDn: process.env["SHARELATEX_LDAP_BIND_DN"], bindCredentials: process.env["SHARELATEX_LDAP_BIND_CREDENTIALS"], bindProperty: process.env["SHARELATEX_LDAP_BIND_PROPERTY"], searchBase: process.env["SHARELATEX_LDAP_SEARCH_BASE"], searchScope: process.env["SHARELATEX_LDAP_SEARCH_SCOPE"], searchFilter: process.env["SHARELATEX_LDAP_SEARCH_FILTER"], searchAttributes: ( (_ldap_search_attribs = process.env["SHARELATEX_LDAP_SEARCH_ATTRIBUTES"]) ? (() => { try { return JSON.parse(_ldap_search_attribs); } catch (error3) { e = error3; return console.error("could not parse SHARELATEX_LDAP_SEARCH_ATTRIBUTES"); } })() : undefined ), groupDnProperty: process.env["SHARELATEX_LDAP_GROUP_DN_PROPERTY"], groupSearchBase: process.env["SHARELATEX_LDAP_GROUP_SEARCH_BASE"], groupSearchScope: process.env["SHARELATEX_LDAP_GROUP_SEARCH_SCOPE"], groupSearchFilter: process.env["SHARELATEX_LDAP_GROUP_SEARCH_FILTER"], groupSearchAttributes: ( (_ldap_group_search_attribs = process.env["SHARELATEX_LDAP_GROUP_SEARCH_ATTRIBUTES"]) ? (() => { try { return JSON.parse(_ldap_group_search_attribs); } catch (error4) { e = error4; return console.error("could not parse SHARELATEX_LDAP_GROUP_SEARCH_ATTRIBUTES"); } })() : undefined ), cache: process.env["SHARELATEX_LDAP_CACHE"] === 'true', timeout: ( (_ldap_timeout = process.env["SHARELATEX_LDAP_TIMEOUT"]) ? (() => { try { return parseIntOrFail(_ldap_timeout); } catch (error5) { e = error5; return console.error("Cannot parse SHARELATEX_LDAP_TIMEOUT"); } })() : undefined ), connectTimeout: ( (_ldap_connect_timeout = process.env["SHARELATEX_LDAP_CONNECT_TIMEOUT"]) ? (() => { try { return parseIntOrFail(_ldap_connect_timeout); } catch (error6) { e = error6; return console.error("Cannot parse SHARELATEX_LDAP_CONNECT_TIMEOUT"); } })() : undefined ) } }; if (process.env["SHARELATEX_LDAP_TLS_OPTS_CA_PATH"]) { let ca, ca_paths; try { ca = JSON.parse(process.env["SHARELATEX_LDAP_TLS_OPTS_CA_PATH"]); } catch (error7) { e = error7; console.error("could not parse SHARELATEX_LDAP_TLS_OPTS_CA_PATH, invalid JSON"); } if (typeof(ca) === 'string') { ca_paths = [ca]; } else if ((typeof(ca) === 'object') && ((ca != null ? ca.length : undefined) != null)) { ca_paths = ca; } else { console.error("problem parsing SHARELATEX_LDAP_TLS_OPTS_CA_PATH"); } settings.ldap.server.tlsOptions = { rejectUnauthorized: process.env["SHARELATEX_LDAP_TLS_OPTS_REJECT_UNAUTH"] === "true", ca:ca_paths // e.g.'/etc/ldap/ca_certs.pem' }; } } if (process.env["SHARELATEX_SAML_ENTRYPOINT"]) { // NOTE: see https://github.com/node-saml/passport-saml/blob/master/README.md for docs of `server` options let _saml_additionalAuthorizeParams, _saml_additionalLogoutParams, _saml_additionalParams, _saml_expiration, _saml_skew; settings.externalAuth = true; settings.saml = { updateUserDetailsOnLogin: process.env["SHARELATEX_SAML_UPDATE_USER_DETAILS_ON_LOGIN"] === 'true', identityServiceName: process.env["SHARELATEX_SAML_IDENTITY_SERVICE_NAME"], emailField: process.env["SHARELATEX_SAML_EMAIL_FIELD"] || process.env["SHARELATEX_SAML_EMAIL_FIELD_NAME"], firstNameField: process.env["SHARELATEX_SAML_FIRST_NAME_FIELD"], lastNameField: process.env["SHARELATEX_SAML_LAST_NAME_FIELD"], server: { // strings entryPoint: process.env["SHARELATEX_SAML_ENTRYPOINT"], callbackUrl: process.env["SHARELATEX_SAML_CALLBACK_URL"], issuer: process.env["SHARELATEX_SAML_ISSUER"], decryptionPvk: process.env["SHARELATEX_SAML_DECRYPTION_PVK"], decryptionCert: process.env["SHARELATEX_SAML_DECRYPTION_CERT"], signatureAlgorithm: process.env["SHARELATEX_SAML_SIGNATURE_ALGORITHM"], identifierFormat: process.env["SHARELATEX_SAML_IDENTIFIER_FORMAT"], attributeConsumingServiceIndex: process.env["SHARELATEX_SAML_ATTRIBUTE_CONSUMING_SERVICE_INDEX"], authnContext: process.env["SHARELATEX_SAML_AUTHN_CONTEXT"], authnRequestBinding: process.env["SHARELATEX_SAML_AUTHN_REQUEST_BINDING"], validateInResponseTo: process.env["SHARELATEX_SAML_VALIDATE_IN_RESPONSE_TO"], cacheProvider: process.env["SHARELATEX_SAML_CACHE_PROVIDER"], logoutUrl: process.env["SHARELATEX_SAML_LOGOUT_URL"], logoutCallbackUrl: process.env["SHARELATEX_SAML_LOGOUT_CALLBACK_URL"], disableRequestedAuthnContext: process.env["SHARELATEX_SAML_DISABLE_REQUESTED_AUTHN_CONTEXT"] === 'true', forceAuthn: process.env["SHARELATEX_SAML_FORCE_AUTHN"] === 'true', skipRequestCompression: process.env["SHARELATEX_SAML_SKIP_REQUEST_COMPRESSION"] === 'true', acceptedClockSkewMs: ( (_saml_skew = process.env["SHARELATEX_SAML_ACCEPTED_CLOCK_SKEW_MS"]) ? (() => { try { return parseIntOrFail(_saml_skew); } catch (error8) { e = error8; return console.error("Cannot parse SHARELATEX_SAML_ACCEPTED_CLOCK_SKEW_MS"); } })() : undefined ), requestIdExpirationPeriodMs: ( (_saml_expiration = process.env["SHARELATEX_SAML_REQUEST_ID_EXPIRATION_PERIOD_MS"]) ? (() => { try { return parseIntOrFail(_saml_expiration); } catch (error9) { e = error9; return console.error("Cannot parse SHARELATEX_SAML_REQUEST_ID_EXPIRATION_PERIOD_MS"); } })() : undefined ), additionalParams: ( (_saml_additionalParams = process.env["SHARELATEX_SAML_ADDITIONAL_PARAMS"]) ? (() => { try { return JSON.parse(_saml_additionalParams); } catch (error10) { e = error10; return console.error("Cannot parse SHARELATEX_SAML_ADDITIONAL_PARAMS"); } })() : undefined ), additionalAuthorizeParams: ( (_saml_additionalAuthorizeParams = process.env["SHARELATEX_SAML_ADDITIONAL_AUTHORIZE_PARAMS"]) ? (() => { try { return JSON.parse(_saml_additionalAuthorizeParams ); } catch (error11) { e = error11; return console.error("Cannot parse SHARELATEX_SAML_ADDITIONAL_AUTHORIZE_PARAMS"); } })() : undefined ), additionalLogoutParams: ( (_saml_additionalLogoutParams = process.env["SHARELATEX_SAML_ADDITIONAL_LOGOUT_PARAMS"]) ? (() => { try { return JSON.parse(_saml_additionalLogoutParams ); } catch (error12) { e = error12; return console.error("Cannot parse SHARELATEX_SAML_ADDITIONAL_LOGOUT_PARAMS"); } })() : undefined ) } }; // SHARELATEX_SAML_CERT cannot be empty // https://github.com/node-saml/passport-saml/commit/f6b1c885c0717f1083c664345556b535f217c102 if (process.env["SHARELATEX_SAML_CERT"]) { settings.saml.server.cert = process.env["SHARELATEX_SAML_CERT"]; settings.saml.server.privateCert = process.env["SHARELATEX_SAML_PRIVATE_CERT"]; } } // Compiler // -------- if (process.env["SANDBOXED_COMPILES"] === "true") { settings.clsi = { dockerRunner: true, docker: { image: process.env["TEX_LIVE_DOCKER_IMAGE"], env: { HOME: "/tmp", PATH: process.env["COMPILER_PATH"] || "/usr/local/texlive/2015/bin/x86_64-linux:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" }, user: "www-data" } }; if ((settings.path == null)) { settings.path = {}; } settings.path.synctexBaseDir = () => "/compile"; if (process.env['SANDBOXED_COMPILES_SIBLING_CONTAINERS'] === 'true') { console.log("Using sibling containers for sandboxed compiles"); if (process.env['SANDBOXED_COMPILES_HOST_DIR']) { settings.path.sandboxedCompilesHostDir = process.env['SANDBOXED_COMPILES_HOST_DIR']; } else { console.error('Sibling containers, but SANDBOXED_COMPILES_HOST_DIR not set'); } } } // Templates // --------- if (process.env["SHARELATEX_TEMPLATES_USER_ID"]) { settings.templates = { mountPointUrl: "/templates", user_id: process.env["SHARELATEX_TEMPLATES_USER_ID"] }; settings.templateLinks = parse(process.env["SHARELATEX_NEW_PROJECT_TEMPLATE_LINKS"]); } // /Learn // ------- if (process.env["SHARELATEX_PROXY_LEARN"] != null) { settings.proxyLearn = parse(process.env["SHARELATEX_PROXY_LEARN"]); } // /References // ----------- if (process.env["SHARELATEX_ELASTICSEARCH_URL"] != null) { settings.references.elasticsearch = {host: process.env["SHARELATEX_ELASTICSEARCH_URL"]}; } // TeX Live Images // ----------- if (process.env["ALL_TEX_LIVE_DOCKER_IMAGES"] != null) { allTexLiveDockerImages = process.env["ALL_TEX_LIVE_DOCKER_IMAGES"].split(','); } if (process.env["ALL_TEX_LIVE_DOCKER_IMAGE_NAMES"] != null) { allTexLiveDockerImageNames = process.env["ALL_TEX_LIVE_DOCKER_IMAGE_NAMES"].split(','); } if (allTexLiveDockerImages != null) { settings.allowedImageNames = []; for (let index = 0; index < allTexLiveDockerImages.length; index++) { const fullImageName = allTexLiveDockerImages[index]; const imageName = Path.basename(fullImageName); const imageDesc = (allTexLiveDockerImageNames != null) ? allTexLiveDockerImageNames[index] : imageName; settings.allowedImageNames.push({ imageName, imageDesc }); } } // With lots of incoming and outgoing HTTP connections to different services, // sometimes long running, it is a good idea to increase the default number // of sockets that Node will hold open. const http = require('http'); http.globalAgent.maxSockets = 300; const https = require('https'); https.globalAgent.maxSockets = 300; module.exports = settings;