UNPKG

verdaccio

Version:

A lightweight private npm proxy registry

104 lines (102 loc) 14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.allow_action = allow_action; exports.defaultSecurity = void 0; exports.getDefaultPlugins = getDefaultPlugins; exports.getSecurity = getSecurity; exports.handleSpecialUnpublish = handleSpecialUnpublish; exports.validatePassword = validatePassword; var _debug = _interopRequireDefault(require("debug")); var _lodash = _interopRequireDefault(require("lodash")); var _constants = require("./constants"); var _logger = require("./logger"); var _utils = require("./utils"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const debug = (0, _debug.default)('verdaccio'); function validatePassword(password, // pragma: allowlist secret minLength = _constants.DEFAULT_MIN_LIMIT_PASSWORD) { return typeof password === 'string' && password.length >= minLength; } function allow_action(action) { return function (user, pkg, callback) { debug('[auth/allow_action]: user: %o', user === null || user === void 0 ? void 0 : user.name); const { name, groups } = user; const groupAccess = pkg[action]; const hasPermission = groupAccess.some(group => name === group || groups.includes(group)); debug('[auth/allow_action]: hasPermission? %o} for user: %o', hasPermission, user === null || user === void 0 ? void 0 : user.name); if (hasPermission) { _logger.logger.info({ user: user.name }, `auth/allow_action: access granted to: @{user}`); return callback(null, true); } if (name) { callback(_utils.ErrorCode.getForbidden(`user ${name} is not allowed to ${action} package ${pkg.name}`)); } else { callback(_utils.ErrorCode.getUnauthorized(`authorization required to ${action} package ${pkg.name}`)); } }; } /** * */ function handleSpecialUnpublish() { return function (user, pkg, callback) { const action = 'unpublish'; // verify whether the unpublish prop has been defined const isUnpublishMissing = _lodash.default.isNil(pkg[action]); const hasGroups = isUnpublishMissing ? false : pkg[action].length > 0; debug('fallback unpublish for @{name} has groups: %o for %o', hasGroups, user === null || user === void 0 ? void 0 : user.name); if (isUnpublishMissing || hasGroups === false) { return callback(null, undefined); } debug('allow_action for %o for %o has groups: %o for %o', action, user === null || user === void 0 ? void 0 : user.name, hasGroups, user); return allow_action(action)(user, pkg, callback); }; } function getDefaultPlugins(logger) { return { authenticate(_user, _password, cb) { // pragma: allowlist secret cb(_utils.ErrorCode.getForbidden(_constants.API_ERROR.BAD_USERNAME_PASSWORD)); }, add_user(_user, _password, cb) { // pragma: allowlist secret return cb(_utils.ErrorCode.getConflict(_constants.API_ERROR.BAD_USERNAME_PASSWORD)); }, // FIXME: allow_action and allow_publish should be in the @verdaccio/types // @ts-ignore allow_access: allow_action('access', logger), // @ts-ignore allow_publish: allow_action('publish', logger), allow_unpublish: handleSpecialUnpublish() }; } const defaultWebTokenOptions = { sign: { // The expiration token for the website is 1 hour expiresIn: _constants.TIME_EXPIRATION_1H }, verify: {} }; const defaultApiTokenConf = { legacy: true, migrateToSecureLegacySignature: false }; const defaultSecurity = exports.defaultSecurity = { web: defaultWebTokenOptions, api: defaultApiTokenConf }; function getSecurity(config) { if (_lodash.default.isNil(config.security) === false) { return _lodash.default.merge(defaultSecurity, config.security); } return defaultSecurity; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZGVidWciLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2Rhc2giLCJfY29uc3RhbnRzIiwiX2xvZ2dlciIsIl91dGlscyIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImRlYnVnIiwiYnVpbGREZWJ1ZyIsInZhbGlkYXRlUGFzc3dvcmQiLCJwYXNzd29yZCIsIm1pbkxlbmd0aCIsIkRFRkFVTFRfTUlOX0xJTUlUX1BBU1NXT1JEIiwibGVuZ3RoIiwiYWxsb3dfYWN0aW9uIiwiYWN0aW9uIiwidXNlciIsInBrZyIsImNhbGxiYWNrIiwibmFtZSIsImdyb3VwcyIsImdyb3VwQWNjZXNzIiwiaGFzUGVybWlzc2lvbiIsInNvbWUiLCJncm91cCIsImluY2x1ZGVzIiwibG9nZ2VyIiwiaW5mbyIsIkVycm9yQ29kZSIsImdldEZvcmJpZGRlbiIsImdldFVuYXV0aG9yaXplZCIsImhhbmRsZVNwZWNpYWxVbnB1Ymxpc2giLCJpc1VucHVibGlzaE1pc3NpbmciLCJfIiwiaXNOaWwiLCJoYXNHcm91cHMiLCJ1bmRlZmluZWQiLCJnZXREZWZhdWx0UGx1Z2lucyIsImF1dGhlbnRpY2F0ZSIsIl91c2VyIiwiX3Bhc3N3b3JkIiwiY2IiLCJBUElfRVJST1IiLCJCQURfVVNFUk5BTUVfUEFTU1dPUkQiLCJhZGRfdXNlciIsImdldENvbmZsaWN0IiwiYWxsb3dfYWNjZXNzIiwiYWxsb3dfcHVibGlzaCIsImFsbG93X3VucHVibGlzaCIsImRlZmF1bHRXZWJUb2tlbk9wdGlvbnMiLCJzaWduIiwiZXhwaXJlc0luIiwiVElNRV9FWFBJUkFUSU9OXzFIIiwidmVyaWZ5IiwiZGVmYXVsdEFwaVRva2VuQ29uZiIsImxlZ2FjeSIsIm1pZ3JhdGVUb1NlY3VyZUxlZ2FjeVNpZ25hdHVyZSIsImRlZmF1bHRTZWN1cml0eSIsImV4cG9ydHMiLCJ3ZWIiLCJhcGkiLCJnZXRTZWN1cml0eSIsImNvbmZpZyIsInNlY3VyaXR5IiwibWVyZ2UiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2F1dGgtdXRpbHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGJ1aWxkRGVidWcgZnJvbSAnZGVidWcnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcblxuaW1wb3J0IHsgcGx1Z2luVXRpbHMgfSBmcm9tICdAdmVyZGFjY2lvL2NvcmUnO1xuaW1wb3J0IHtcbiAgQVBJVG9rZW5PcHRpb25zLFxuICBDYWxsYmFjayxcbiAgQ29uZmlnLFxuICBKV1RPcHRpb25zLFxuICBQYWNrYWdlLFxuICBSZW1vdGVVc2VyLFxuICBTZWN1cml0eSxcbn0gZnJvbSAnQHZlcmRhY2Npby90eXBlcyc7XG5cbmltcG9ydCB7IEFQSV9FUlJPUiwgREVGQVVMVF9NSU5fTElNSVRfUEFTU1dPUkQsIFRJTUVfRVhQSVJBVElPTl8xSCB9IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyJztcbmltcG9ydCB7IEVycm9yQ29kZSB9IGZyb20gJy4vdXRpbHMnO1xuXG5jb25zdCBkZWJ1ZyA9IGJ1aWxkRGVidWcoJ3ZlcmRhY2NpbycpO1xuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVQYXNzd29yZChcbiAgcGFzc3dvcmQ6IHN0cmluZywgLy8gcHJhZ21hOiBhbGxvd2xpc3Qgc2VjcmV0XG4gIG1pbkxlbmd0aDogbnVtYmVyID0gREVGQVVMVF9NSU5fTElNSVRfUEFTU1dPUkRcbik6IGJvb2xlYW4ge1xuICByZXR1cm4gdHlwZW9mIHBhc3N3b3JkID09PSAnc3RyaW5nJyAmJiBwYXNzd29yZC5sZW5ndGggPj0gbWluTGVuZ3RoO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWxsb3dfYWN0aW9uKGFjdGlvbjogc3RyaW5nKTogRnVuY3Rpb24ge1xuICByZXR1cm4gZnVuY3Rpb24gKHVzZXI6IFJlbW90ZVVzZXIsIHBrZzogUGFja2FnZSwgY2FsbGJhY2s6IENhbGxiYWNrKTogdm9pZCB7XG4gICAgZGVidWcoJ1thdXRoL2FsbG93X2FjdGlvbl06IHVzZXI6ICVvJywgdXNlcj8ubmFtZSk7XG4gICAgY29uc3QgeyBuYW1lLCBncm91cHMgfSA9IHVzZXI7XG4gICAgY29uc3QgZ3JvdXBBY2Nlc3MgPSBwa2dbYWN0aW9uXTtcbiAgICBjb25zdCBoYXNQZXJtaXNzaW9uID0gZ3JvdXBBY2Nlc3Muc29tZSgoZ3JvdXApID0+IG5hbWUgPT09IGdyb3VwIHx8IGdyb3Vwcy5pbmNsdWRlcyhncm91cCkpO1xuICAgIGRlYnVnKCdbYXV0aC9hbGxvd19hY3Rpb25dOiBoYXNQZXJtaXNzaW9uPyAlb30gZm9yIHVzZXI6ICVvJywgaGFzUGVybWlzc2lvbiwgdXNlcj8ubmFtZSk7XG5cbiAgICBpZiAoaGFzUGVybWlzc2lvbikge1xuICAgICAgbG9nZ2VyLmluZm8oeyB1c2VyOiB1c2VyLm5hbWUgfSwgYGF1dGgvYWxsb3dfYWN0aW9uOiBhY2Nlc3MgZ3JhbnRlZCB0bzogQHt1c2VyfWApO1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIHRydWUpO1xuICAgIH1cblxuICAgIGlmIChuYW1lKSB7XG4gICAgICBjYWxsYmFjayhcbiAgICAgICAgRXJyb3JDb2RlLmdldEZvcmJpZGRlbihgdXNlciAke25hbWV9IGlzIG5vdCBhbGxvd2VkIHRvICR7YWN0aW9ufSBwYWNrYWdlICR7cGtnLm5hbWV9YClcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNhbGxiYWNrKFxuICAgICAgICBFcnJvckNvZGUuZ2V0VW5hdXRob3JpemVkKGBhdXRob3JpemF0aW9uIHJlcXVpcmVkIHRvICR7YWN0aW9ufSBwYWNrYWdlICR7cGtnLm5hbWV9YClcbiAgICAgICk7XG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYW5kbGVTcGVjaWFsVW5wdWJsaXNoKCk6IGFueSB7XG4gIHJldHVybiBmdW5jdGlvbiAodXNlcjogUmVtb3RlVXNlciwgcGtnOiBQYWNrYWdlLCBjYWxsYmFjazogQ2FsbGJhY2spOiB2b2lkIHtcbiAgICBjb25zdCBhY3Rpb24gPSAndW5wdWJsaXNoJztcbiAgICAvLyB2ZXJpZnkgd2hldGhlciB0aGUgdW5wdWJsaXNoIHByb3AgaGFzIGJlZW4gZGVmaW5lZFxuICAgIGNvbnN0IGlzVW5wdWJsaXNoTWlzc2luZzogYm9vbGVhbiA9IF8uaXNOaWwocGtnW2FjdGlvbl0pO1xuICAgIGNvbnN0IGhhc0dyb3VwczogYm9vbGVhbiA9IGlzVW5wdWJsaXNoTWlzc2luZyA/IGZhbHNlIDogcGtnW2FjdGlvbl0ubGVuZ3RoID4gMDtcbiAgICBkZWJ1ZygnZmFsbGJhY2sgdW5wdWJsaXNoIGZvciBAe25hbWV9IGhhcyBncm91cHM6ICVvIGZvciAlbycsIGhhc0dyb3VwcywgdXNlcj8ubmFtZSk7XG4gICAgaWYgKGlzVW5wdWJsaXNoTWlzc2luZyB8fCBoYXNHcm91cHMgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgZGVidWcoJ2FsbG93X2FjdGlvbiBmb3IgJW8gZm9yICVvIGhhcyBncm91cHM6ICVvIGZvciAlbycsIGFjdGlvbiwgdXNlcj8ubmFtZSwgaGFzR3JvdXBzLCB1c2VyKTtcbiAgICByZXR1cm4gYWxsb3dfYWN0aW9uKGFjdGlvbikodXNlciwgcGtnLCBjYWxsYmFjayk7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREZWZhdWx0UGx1Z2lucyhsb2dnZXI6IGFueSk6IHBsdWdpblV0aWxzLkF1dGg8Q29uZmlnPiB7XG4gIHJldHVybiB7XG4gICAgYXV0aGVudGljYXRlKF91c2VyOiBzdHJpbmcsIF9wYXNzd29yZDogc3RyaW5nLCBjYjogQ2FsbGJhY2spOiB2b2lkIHtcbiAgICAgIC8vIHByYWdtYTogYWxsb3dsaXN0IHNlY3JldFxuICAgICAgY2IoRXJyb3JDb2RlLmdldEZvcmJpZGRlbihBUElfRVJST1IuQkFEX1VTRVJOQU1FX1BBU1NXT1JEKSk7XG4gICAgfSxcblxuICAgIGFkZF91c2VyKF91c2VyOiBzdHJpbmcsIF9wYXNzd29yZDogc3RyaW5nLCBjYjogQ2FsbGJhY2spOiB2b2lkIHtcbiAgICAgIC8vIHByYWdtYTogYWxsb3dsaXN0IHNlY3JldFxuICAgICAgcmV0dXJuIGNiKEVycm9yQ29kZS5nZXRDb25mbGljdChBUElfRVJST1IuQkFEX1VTRVJOQU1FX1BBU1NXT1JEKSk7XG4gICAgfSxcblxuICAgIC8vIEZJWE1FOiBhbGxvd19hY3Rpb24gYW5kIGFsbG93X3B1Ymxpc2ggc2hvdWxkIGJlIGluIHRoZSBAdmVyZGFjY2lvL3R5cGVzXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIGFsbG93X2FjY2VzczogYWxsb3dfYWN0aW9uKCdhY2Nlc3MnLCBsb2dnZXIpLFxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBhbGxvd19wdWJsaXNoOiBhbGxvd19hY3Rpb24oJ3B1Ymxpc2gnLCBsb2dnZXIpLFxuICAgIGFsbG93X3VucHVibGlzaDogaGFuZGxlU3BlY2lhbFVucHVibGlzaCgpLFxuICB9O1xufVxuXG5jb25zdCBkZWZhdWx0V2ViVG9rZW5PcHRpb25zOiBKV1RPcHRpb25zID0ge1xuICBzaWduOiB7XG4gICAgLy8gVGhlIGV4cGlyYXRpb24gdG9rZW4gZm9yIHRoZSB3ZWJzaXRlIGlzIDEgaG91clxuICAgIGV4cGlyZXNJbjogVElNRV9FWFBJUkFUSU9OXzFILFxuICB9LFxuICB2ZXJpZnk6IHt9LFxufTtcblxuY29uc3QgZGVmYXVsdEFwaVRva2VuQ29uZjogQVBJVG9rZW5PcHRpb25zID0ge1xuICBsZWdhY3k6IHRydWUsXG4gIG1pZ3JhdGVUb1NlY3VyZUxlZ2FjeVNpZ25hdHVyZTogZmFsc2UsXG59O1xuXG5leHBvcnQgY29uc3QgZGVmYXVsdFNlY3VyaXR5OiBTZWN1cml0eSA9IHtcbiAgd2ViOiBkZWZhdWx0V2ViVG9rZW5PcHRpb25zLFxuICBhcGk6IGRlZmF1bHRBcGlUb2tlbkNvbmYsXG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2VjdXJpdHkoY29uZmlnOiBDb25maWcpOiBTZWN1cml0eSB7XG4gIGlmIChfLmlzTmlsKGNvbmZpZy5zZWN1cml0eSkgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuIF8ubWVyZ2UoZGVmYXVsdFNlY3VyaXR5LCBjb25maWcuc2VjdXJpdHkpO1xuICB9XG5cbiAgcmV0dXJuIGRlZmF1bHRTZWN1cml0eTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQSxJQUFBQSxNQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFGLHNCQUFBLENBQUFDLE9BQUE7QUFhQSxJQUFBRSxVQUFBLEdBQUFGLE9BQUE7QUFDQSxJQUFBRyxPQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxNQUFBLEdBQUFKLE9BQUE7QUFBb0MsU0FBQUQsdUJBQUFNLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFDLFVBQUEsR0FBQUQsQ0FBQSxLQUFBRSxPQUFBLEVBQUFGLENBQUE7QUFFcEMsTUFBTUcsS0FBSyxHQUFHLElBQUFDLGNBQVUsRUFBQyxXQUFXLENBQUM7QUFFOUIsU0FBU0MsZ0JBQWdCQSxDQUM5QkMsUUFBZ0I7QUFBRTtBQUNsQkMsU0FBaUIsR0FBR0MscUNBQTBCLEVBQ3JDO0VBQ1QsT0FBTyxPQUFPRixRQUFRLEtBQUssUUFBUSxJQUFJQSxRQUFRLENBQUNHLE1BQU0sSUFBSUYsU0FBUztBQUNyRTtBQUVPLFNBQVNHLFlBQVlBLENBQUNDLE1BQWMsRUFBWTtFQUNyRCxPQUFPLFVBQVVDLElBQWdCLEVBQUVDLEdBQVksRUFBRUMsUUFBa0IsRUFBUTtJQUN6RVgsS0FBSyxDQUFDLCtCQUErQixFQUFFUyxJQUFJLGFBQUpBLElBQUksdUJBQUpBLElBQUksQ0FBRUcsSUFBSSxDQUFDO0lBQ2xELE1BQU07TUFBRUEsSUFBSTtNQUFFQztJQUFPLENBQUMsR0FBR0osSUFBSTtJQUM3QixNQUFNSyxXQUFXLEdBQUdKLEdBQUcsQ0FBQ0YsTUFBTSxDQUFDO0lBQy9CLE1BQU1PLGFBQWEsR0FBR0QsV0FBVyxDQUFDRSxJQUFJLENBQUVDLEtBQUssSUFBS0ws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