UNPKG

@verdaccio/config

Version:

Verdaccio Configuration

209 lines (198 loc) 8.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultUserRateLimiting = exports.WEB_TITLE = exports.Config = void 0; exports.isNodeVersionGreaterThan21 = isNodeVersionGreaterThan21; var _debug = _interopRequireDefault(require("debug")); var _lodash = _interopRequireDefault(require("lodash")); var _nodeAssert = _interopRequireDefault(require("node:assert")); var _core = require("@verdaccio/core"); var _warningUtils = require("@verdaccio/core/build/warning-utils"); var _agent = require("./agent"); var _packageAccess = require("./package-access"); var _security = require("./security"); var _serverSettings = _interopRequireDefault(require("./serverSettings")); var _token = require("./token"); var _uplinks = require("./uplinks"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const strategicConfigProps = ['uplinks', 'packages']; const allowedEnvConfig = ['http_proxy', 'https_proxy', 'no_proxy']; const debug = (0, _debug.default)('verdaccio:config'); const WEB_TITLE = exports.WEB_TITLE = 'Verdaccio'; // we limit max 1000 request per 15 minutes on user endpoints const defaultUserRateLimiting = exports.defaultUserRateLimiting = { windowMs: 15 * 60 * 1000, // 15 minutes max: 1000 }; function isNodeVersionGreaterThan21() { const [major, minor] = process.versions.node.split('.').map(Number); return major > 21 || major === 21 && minor >= 0; } const TOKEN_VALID_LENGTH = 32; /** * Coordinates the application configuration */ class Config { /** * @deprecated use configPath or config.getConfigPath(); */ // @ts-ignore constructor(config, // forceEnhancedLegacySignature is a property that // allows switch a new legacy aes signature token signature // for older versions do not want to have this new signature model // this property must be false configOverrideOptions = { forceMigrateToSecureLegacySignature: true }) { const self = this; this.storage = process.env.VERDACCIO_STORAGE_PATH || config.storage; if (!config.configPath) { // backport self_path for previous to version 6 // @ts-expect-error config.configPath = config.config_path ?? config.self_path; if (!config.configPath) { throw new Error('configPath property is required'); } } this.configOverrideOptions = configOverrideOptions; this.configPath = config.configPath; this.self_path = this.configPath; debug('config path: %s', this.configPath); this.plugins = config.plugins; this.security = _lodash.default.merge( // override the default security configuration via constructor _lodash.default.merge(_security.defaultSecurity, { api: { migrateToSecureLegacySignature: this.configOverrideOptions.forceMigrateToSecureLegacySignature } }), config.security); this.server = { ..._serverSettings.default, ...config.server }; this.flags = { searchRemote: config.flags?.searchRemote ?? true, changePassword: config.flags?.changePassword ?? false, webLogin: config.flags?.webLogin ?? false, createUser: config.flags?.createUser ?? false }; this.user_agent = config.user_agent; for (const configProp in config) { if (self[configProp] == null) { self[configProp] = config[configProp]; } } if (typeof this.user_agent === 'undefined') { // by default user agent is hidden debug('set default user agent'); this.user_agent = (0, _agent.getUserAgent)(false); } this.userRateLimit = { ...defaultUserRateLimiting, ...config?.userRateLimit }; // some weird shell scripts are valid yaml files parsed as string (0, _nodeAssert.default)(_core.validationUtils.isObject(config), _core.APP_ERROR.CONFIG_NOT_VALID); // sanity check for strategic config properties strategicConfigProps.forEach(function (x) { if (self[x] == null) { self[x] = {}; } (0, _nodeAssert.default)(_core.validationUtils.isObject(self[x]), `CONFIG: bad "${x}" value (object expected)`); }); this.uplinks = (0, _uplinks.sanityCheckUplinksProps)((0, _uplinks.uplinkSanityCheck)(this.uplinks)); this.packages = (0, _packageAccess.normalisePackageAccess)(self.packages); // loading these from ENV if aren't in config allowedEnvConfig.forEach(envConf => { if (!(envConf in self)) { self[envConf] = process.env[envConf] || process.env[envConf.toUpperCase()]; } }); // unique identifier of self server (or a cluster), used to avoid loops // @ts-ignore if (!this.server_id) { this.server_id = _core.cryptoUtils.generateRandomHexString(6); } } getMigrateToSecureLegacySignature() { return this.security.api.migrateToSecureLegacySignature; } getConfigPath() { return this.configPath; } /** * Check for package spec * @param pkgName - package name * @returns package access * @deprecated use core.authUtils instead */ getMatchedPackagesSpec(pkgName) { // TODO: remove this method and replace by library utils return _core.authUtils.getMatchedPackagesSpec(pkgName, this.packages); } /** * Verify if the secret complies with the required structure * - If the secret is not provided, it will generate a new one * - For any Node.js version the new secret will be 32 characters long (to allow compatibility with modern Node.js versions) * - If the secret is provided: * - If Node.js 22 or higher, the secret must be 32 characters long thus the application will fail on startup * - If Node.js 21 or lower, the secret will be used as is but will display a deprecation warning * - If the property `security.api.migrateToSecureLegacySignature` is provided and set to true, the secret will be * generated with the new signature model * @secret external secret key */ checkSecretKey(secret) { debug('checking secret key init'); if (typeof secret === 'string' && _lodash.default.isEmpty(secret) === false) { debug('checking secret key length %s', secret.length); if (secret.length > TOKEN_VALID_LENGTH) { if (isNodeVersionGreaterThan21()) { debug('is node version greater than 21'); if (this.getMigrateToSecureLegacySignature() === true) { this.secret = (0, _token.generateRandomSecretKey)(); debug('rewriting secret key with length %s', this.secret.length); return this.secret; } // oops, user needs to generate a new secret key debug('secret does not comply with the required length, current length %d, application will fail on startup', secret.length); throw new Error(`Invalid storage secret key length, must be 32 characters long but is ${secret.length}. The secret length in Node.js 22 or higher must be 32 characters long. Please consider generate a new one. Learn more at https://verdaccio.org/docs/configuration/#.verdaccio-db`); } else { debug('is node version lower than 22'); if (this.getMigrateToSecureLegacySignature() === true) { this.secret = (0, _token.generateRandomSecretKey)(); debug('rewriting secret key with length %s', this.secret.length); return this.secret; } debug('triggering deprecation warning for secret key length %s', secret.length); // still using Node.js versions previous to 22, but we need to emit a deprecation warning // deprecation warning, secret key is too long and must be 32 // this will be removed in the next major release and will produce an error _core.warningUtils.emit(_warningUtils.Codes.VERWAR007); this.secret = secret; return this.secret; } } else if (secret.length === TOKEN_VALID_LENGTH) { debug('detected valid secret key length %s', secret.length); this.secret = secret; return this.secret; } debug('reusing previous key with length %s', secret.length); this.secret = secret; return this.secret; } else { // generate a new a secret key // FUTURE: this might be an external secret key, perhaps within config file? debug('generating a new secret key'); this.secret = (0, _token.generateRandomSecretKey)(); debug('generated a new secret key length %s', this.secret?.length); return this.secret; } } } exports.Config = Config; //# sourceMappingURL=config.js.map