cnpmcore
Version:
268 lines • 24.6 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SavePackageVersionController = void 0;
const lodash_1 = require("lodash");
const egg_errors_1 = require("egg-errors");
const tegg_1 = require("@eggjs/tegg");
const ssri = __importStar(require("ssri"));
const validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
const typebox_1 = require("@sinclair/typebox");
const AbstractController_1 = require("../AbstractController");
const PackageUtil_1 = require("../../../common/PackageUtil");
const PackageManagerService_1 = require("../../../core/service/PackageManagerService");
const typebox_2 = require("../../typebox");
const RegistryManagerService_1 = require("../../../core/service/RegistryManagerService");
const CacheAdapter_1 = require("../../../common/adapter/CacheAdapter");
const STRICT_CHECK_TARBALL_FIELDS = ['name', 'version', 'scripts', 'dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies', 'license', 'licenses', 'bin'];
const FullPackageRule = typebox_1.Type.Object({
name: typebox_2.Name,
// Since we don't validate versions & _attachments previous, here we use Type.Any() just for object validate
versions: typebox_1.Type.Optional(typebox_1.Type.Any()),
_attachments: typebox_1.Type.Optional(typebox_1.Type.Any()),
description: typebox_1.Type.Optional(typebox_2.Description),
'dist-tags': typebox_1.Type.Optional(typebox_1.Type.Record(typebox_1.Type.String(), typebox_1.Type.String())),
readme: typebox_1.Type.Optional(typebox_1.Type.String({ transform: ['trim'] })),
});
// base64 regex https://stackoverflow.com/questions/475074/regex-to-parse-or-validate-base64-data/475217#475217
const PACKAGE_ATTACH_DATA_RE = /^[A-Za-z0-9+/]{4}/;
let SavePackageVersionController = class SavePackageVersionController extends AbstractController_1.AbstractController {
// https://github.com/cnpm/cnpmjs.org/blob/master/docs/registry-api.md#publish-a-new-package
// https://github.com/npm/libnpmpublish/blob/main/publish.js#L43
async save(ctx, fullname, pkg) {
this.validateNpmCommand(ctx);
ctx.tValidate(FullPackageRule, pkg);
const { user } = await this.ensurePublishAccess(ctx, fullname, false);
fullname = fullname.trim();
if (fullname !== pkg.name) {
throw new egg_errors_1.UnprocessableEntityError(`fullname(${fullname}) not match package.name(${pkg.name})`);
}
// Using https://github.com/npm/validate-npm-package-name to validate package name
const validateResult = (0, validate_npm_package_name_1.default)(pkg.name);
if (!validateResult.validForNewPackages) {
// if pkg already exists, still allow to publish
const [scope, name] = (0, PackageUtil_1.getScopeAndName)(fullname);
const pkg = await this.packageRepository.findPackage(scope, name);
if (!pkg) {
const errors = (validateResult.errors || validateResult.warnings || []).join(', ');
throw new egg_errors_1.UnprocessableEntityError(`package.name invalid, errors: ${errors}`);
}
}
const versions = Object.values(pkg.versions);
if (versions.length === 0) {
throw new egg_errors_1.UnprocessableEntityError('versions is empty');
}
// auth maintainter
const attachments = pkg._attachments ?? {};
const attachmentFilename = Object.keys(attachments)[0];
if (!attachmentFilename) {
// `deprecated: ''` meaning remove deprecated message
const isDeprecatedRequest = versions.some(version => 'deprecated' in version);
// handle deprecated request
// PUT /:fullname?write=true
// https://github.com/npm/cli/blob/latest/lib/commands/deprecate.js#L48
if (isDeprecatedRequest) {
return await this.saveDeprecatedVersions(pkg.name, versions);
}
// invalid attachments
throw new egg_errors_1.UnprocessableEntityError('_attachments is empty');
}
// handle add new version
const packageVersion = versions[0];
// check version format
ctx.tValidate(typebox_2.VersionRule, packageVersion);
const attachment = attachments[attachmentFilename];
const distTags = pkg['dist-tags'] ?? {};
let tagNames = Object.keys(distTags);
if (tagNames.length === 0) {
throw new egg_errors_1.UnprocessableEntityError('dist-tags is empty');
}
const [scope, name] = (0, PackageUtil_1.getScopeAndName)(fullname);
// see @https://github.com/cnpm/cnpmcore/issues/574
// add default latest tag
if (!pkg['dist-tags'].latest) {
const existsPkg = await this.packageRepository.findPackage(scope, name);
const existsLatestTag = existsPkg && await this.packageRepository.findPackageTag(existsPkg?.packageId, 'latest');
if (!existsPkg || !existsLatestTag) {
this.logger.warn('[package:version:add] add default latest tag');
pkg['dist-tags'].latest = pkg['dist-tags'][tagNames[0]];
tagNames = [...tagNames, 'latest'];
}
}
const tagWithVersion = { tag: tagNames[0], version: distTags[tagNames[0]] };
ctx.tValidate(typebox_2.TagWithVersionRule, tagWithVersion);
if (tagWithVersion.version !== packageVersion.version) {
throw new egg_errors_1.UnprocessableEntityError(`dist-tags version "${tagWithVersion.version}" not match package version "${packageVersion.version}"`);
}
// check attachment data format and size
if (!attachment.data || typeof attachment.data !== 'string') {
throw new egg_errors_1.UnprocessableEntityError('attachment.data format invalid');
}
if (!PACKAGE_ATTACH_DATA_RE.test(attachment.data)) {
throw new egg_errors_1.UnprocessableEntityError('attachment.data string format invalid');
}
const tarballBytes = Buffer.from(attachment.data, 'base64');
if (tarballBytes.length !== attachment.length) {
throw new egg_errors_1.UnprocessableEntityError(`attachment size ${attachment.length} not match download size ${tarballBytes.length}`);
}
// check integrity or shasum
const integrity = packageVersion.dist?.integrity;
// for content security reason
// check integrity
if (integrity) {
const algorithm = ssri.checkData(tarballBytes, integrity);
if (!algorithm) {
throw new egg_errors_1.UnprocessableEntityError('dist.integrity invalid');
}
}
else {
const integrityObj = ssri.fromData(tarballBytes, {
algorithms: ['sha1'],
});
const shasum = integrityObj.sha1[0].hexDigest();
if (packageVersion.dist?.shasum && packageVersion.dist.shasum !== shasum) {
// if integrity not exists, check shasum
throw new egg_errors_1.UnprocessableEntityError('dist.shasum invalid');
}
}
// https://github.com/cnpm/cnpmcore/issues/542
// check tgz & manifests
if (this.config.cnpmcore.strictValidateTarballPkg) {
const tarballPkg = await (0, PackageUtil_1.extractPackageJSON)(tarballBytes);
const versionManifest = pkg.versions[tarballPkg.version];
const diffKeys = STRICT_CHECK_TARBALL_FIELDS.filter(key => {
const targetKey = key;
return !(0, lodash_1.isEqual)(tarballPkg[key], versionManifest[targetKey]);
});
if (diffKeys.length > 0) {
throw new egg_errors_1.UnprocessableEntityError(`${diffKeys} mismatch between tarball and manifest`);
}
}
// make sure readme is string
const readme = typeof packageVersion.readme === 'string' ? packageVersion.readme : '';
// remove readme
packageVersion.readme = undefined;
// make sure description is string
if (typeof packageVersion.description !== 'string') {
packageVersion.description = '';
}
const registry = await this.registryManagerService.ensureSelfRegistry();
let packageVersionEntity;
const lockName = `${pkg.name}:publish`;
const lockRes = await this.cacheAdapter.usingLock(`${pkg.name}:publish`, 60, async () => {
packageVersionEntity = await this.packageManagerService.publish({
scope,
name,
version: packageVersion.version,
description: packageVersion.description,
packageJson: packageVersion,
readme,
dist: {
content: tarballBytes,
},
tags: tagNames,
registryId: registry.registryId,
isPrivate: true,
}, user);
});
// lock fail
if (!lockRes) {
this.logger.warn('[package:version:add] check lock:%s fail', lockName);
throw new egg_errors_1.ConflictError('Unable to create the publication lock, please try again later.');
}
this.logger.info('[package:version:add] %s@%s, packageVersionId: %s, tag: %s, userId: %s', packageVersion.name, packageVersion.version, packageVersionEntity?.packageVersionId, tagWithVersion.tag, user?.userId);
ctx.status = 201;
return {
ok: true,
rev: `${packageVersionEntity?.id}-${packageVersionEntity?.packageVersionId}`,
};
}
// https://github.com/cnpm/cnpmjs.org/issues/415
async saveDeprecatedVersions(fullname, versions) {
const pkg = await this.getPackageEntityByFullname(fullname);
await this.packageManagerService.saveDeprecatedVersions(pkg, versions.map(v => {
return { version: v.version, deprecated: v.deprecated };
}));
return { ok: true };
}
validateNpmCommand(ctx) {
// forbidden star/unstar request
// npm@6: referer: 'star [REDACTED]'
// npm@>=7: 'npm-command': 'star'
let command = ctx.get('npm-command');
if (!command) {
command = ctx.get('referer').split(' ', 1)[0];
}
if (command === 'star' || command === 'unstar') {
throw new egg_errors_1.ForbiddenError(`npm ${command} is not allowed`);
}
}
};
exports.SavePackageVersionController = SavePackageVersionController;
__decorate([
(0, tegg_1.Inject)(),
__metadata("design:type", PackageManagerService_1.PackageManagerService)
], SavePackageVersionController.prototype, "packageManagerService", void 0);
__decorate([
(0, tegg_1.Inject)(),
__metadata("design:type", RegistryManagerService_1.RegistryManagerService)
], SavePackageVersionController.prototype, "registryManagerService", void 0);
__decorate([
(0, tegg_1.Inject)(),
__metadata("design:type", CacheAdapter_1.CacheAdapter)
], SavePackageVersionController.prototype, "cacheAdapter", void 0);
__decorate([
(0, tegg_1.HTTPMethod)({
// PUT /:fullname
// https://www.npmjs.com/package/path-to-regexp#custom-matching-parameters
path: `/:fullname(${PackageUtil_1.FULLNAME_REG_STRING})`,
method: tegg_1.HTTPMethodEnum.PUT,
}),
__param(0, (0, tegg_1.Context)()),
__param(1, (0, tegg_1.HTTPParam)()),
__param(2, (0, tegg_1.HTTPBody)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, String, Object]),
__metadata("design:returntype", Promise)
], SavePackageVersionController.prototype, "save", null);
exports.SavePackageVersionController = SavePackageVersionController = __decorate([
(0, tegg_1.HTTPController)()
], SavePackageVersionController);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2F2ZVBhY2thZ2VWZXJzaW9uQ29udHJvbGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2FwcC9wb3J0L2NvbnRyb2xsZXIvcGFja2FnZS9TYXZlUGFja2FnZVZlcnNpb25Db250cm9sbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQ0EsbUNBQWlDO0FBQ2pDLDJDQUlvQjtBQUNwQixzQ0FTcUI7QUFDckIsMkNBQTZCO0FBQzdCLDBGQUErRDtBQUMvRCwrQ0FBaUQ7QUFDakQsOERBQTJEO0FBQzNELDZEQUF1RztBQUN2Ryx1RkFBb0Y7QUFFcEYsMkNBS3VCO0FBQ3ZCLHlGQUFzRjtBQUV0Rix1RUFBb0U7QUFFcEUsTUFBTSwyQkFBMkIsR0FBMEIsQ0FBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUUsa0JBQWtCLEVBQUUsc0JBQXNCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxLQUFLLENBQUUsQ0FBQztBQWN6TSxNQUFNLGVBQWUsR0FBRyxjQUFJLENBQUMsTUFBTSxDQUFDO0lBQ2xDLElBQUksRUFBRSxjQUFRO0lBQ2QsNEdBQTRHO0lBQzVHLFFBQVEsRUFBRSxjQUFJLENBQUMsUUFBUSxDQUFDLGNBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNuQyxZQUFZLEVBQUUsY0FBSSxDQUFDLFFBQVEsQ0FBQyxjQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDdkMsV0FBVyxFQUFFLGNBQUksQ0FBQyxRQUFRLENBQUMscUJBQWUsQ0FBQztJQUMzQyxXQUFXLEVBQUUsY0FBSSxDQUFDLFFBQVEsQ0FBQyxjQUFJLENBQUMsTUFBTSxDQUFDLGNBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxjQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNyRSxNQUFNLEVBQUUsY0FBSSxDQUFDLFFB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