diff --git a/src/registry/domain/validators/index.ts b/src/registry/domain/validators/index.ts index 3cdef5b4c..049eb0fe4 100644 --- a/src/registry/domain/validators/index.ts +++ b/src/registry/domain/validators/index.ts @@ -5,6 +5,7 @@ import ocCliVersionValidator from './oc-cli-version'; import packageJsonValidator from './package-json-validator'; import pluginsRequirementsValidator from './plugins-requirements'; import registryConfigurationValidator from './registry-configuration'; +import templateOcVersionValidator from './templace-oc-version'; import nodeVersionValidator from './node-version'; import uploadedPackageValidator from './uploaded-package'; @@ -19,6 +20,8 @@ export const validatePackage = uploadedPackageValidator; export const validatePackageJson = packageJsonValidator; export const validatePluginsRequirements = pluginsRequirementsValidator; export const validateRegistryConfiguration = registryConfigurationValidator; +export const validateTemplateOcVersion = templateOcVersionValidator; + export function validateVersion(version: string): boolean { return !!semver.valid(version); } diff --git a/src/registry/domain/validators/templace-oc-version.ts b/src/registry/domain/validators/templace-oc-version.ts new file mode 100644 index 000000000..1ed0087db --- /dev/null +++ b/src/registry/domain/validators/templace-oc-version.ts @@ -0,0 +1,33 @@ +import path from 'node:path'; +import fs from 'fs-extra'; +import semver from 'semver'; + +const packageInfo = fs.readJsonSync( + path.join(__dirname, '..', '..', '..', '..', 'package.json') +); + +type OkResult = { isValid: true }; +type ErrorResult = { + isValid: false; + error: { + registryVersion: string; + minOcVersion: string; + code: string; + }; +}; +type Result = OkResult | ErrorResult; + +export default function templateOcVersion(minOcVersion: string): Result { + if (semver.lt(packageInfo.version, minOcVersion)) { + return { + isValid: false, + error: { + registryVersion: packageInfo.version, + minOcVersion, + code: 'old_version' + } + }; + } + + return { isValid: true }; +} diff --git a/src/registry/routes/helpers/get-component.ts b/src/registry/routes/helpers/get-component.ts index 791be2922..651a21ff4 100644 --- a/src/registry/routes/helpers/get-component.ts +++ b/src/registry/routes/helpers/get-component.ts @@ -18,6 +18,7 @@ import RequireWrapper from '../../domain/require-wrapper'; import * as sanitiser from '../../domain/sanitiser'; import * as urlBuilder from '../../domain/url-builder'; import * as validator from '../../domain/validators'; +import { validateTemplateOcVersion } from '../../domain/validators'; import applyDefaultValues from './apply-default-values'; import * as getComponentFallback from './get-component-fallback'; import GetComponentRetrievingInfo from './get-component-retrieving-info'; @@ -203,6 +204,24 @@ export default function getComponent(conf: Config, repository: Repository) { }); } + if (component.oc.files.template.minOcVersion) { + const templateOcVersionResult = validateTemplateOcVersion( + component.oc.files.template.minOcVersion + ); + if (!templateOcVersionResult.isValid) { + return callback({ + status: 400, + response: { + code: 'TEMPLATE_REQUIRES_HIGHER_OC_VERSION', + error: strings.errors.cli.TEMPLATE_OC_VERSION_NOT_VALID( + templateOcVersionResult.error.minOcVersion, + templateOcVersionResult.error.registryVersion + ) + } + }); + } + } + // Support legacy templates let templateType = component.oc.files.template.type; const isLegacyTemplate = isTemplateLegacy(templateType); diff --git a/src/registry/routes/publish.ts b/src/registry/routes/publish.ts index 30b166f01..299a6c5a3 100644 --- a/src/registry/routes/publish.ts +++ b/src/registry/routes/publish.ts @@ -3,6 +3,7 @@ import strings from '../../resources/index'; import extractPackage from '../domain/extract-package'; import type { Repository } from '../domain/repository'; import * as validator from '../domain/validators'; +import { validateTemplateOcVersion } from '../domain/validators'; export default function publish(repository: Repository) { return async (req: Request, res: Response): Promise => { @@ -56,6 +57,24 @@ export default function publish(repository: Repository) { try { const pkgDetails = await extractPackage(files, res.conf.tarExtractMode); + if (pkgDetails.packageJson.oc.files.template.minOcVersion) { + const templateOcVersionResult = validateTemplateOcVersion( + pkgDetails.packageJson.oc.files.template.minOcVersion + ); + if (!templateOcVersionResult.isValid) { + res.errorDetails = `Your template requires a version of OC higher than ${templateOcVersionResult.error.minOcVersion}`; + res.status(409).json({ + code: 'template_oc_version_not_valid', + error: strings.errors.cli.TEMPLATE_OC_VERSION_NOT_VALID( + templateOcVersionResult.error.minOcVersion, + templateOcVersionResult.error.registryVersion + ), + details: templateOcVersionResult.error + }); + return; + } + } + try { await repository.publishComponent({ pkgDetails, diff --git a/src/resources/index.ts b/src/resources/index.ts index 7e9904456..4e68e1272 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -212,6 +212,11 @@ export default { `Error requiring oc-template: "${template}" not found`, TEMPLATE_TYPE_NOT_VALID: (template: string): string => `Error requiring oc-template: "${template}" is not a valid oc-template`, + TEMPLATE_OC_VERSION_NOT_VALID: ( + template: string, + version: string + ): string => + `Your template requires a version of OC higher than ${template} but your OC version is ${version}`, TEMPLATE_DEP_MISSING: (template: string, path: string): string => `Template dependency missing. To fix it run:\n\nnpm install --save-dev ${template}-compiler --prefix ${path}\n\n` }, diff --git a/src/types.ts b/src/types.ts index 370498463..c4f0f357a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -85,6 +85,7 @@ interface OcConfiguration { src: string; type: string; version: string; + minOcVersion?: string; size?: number; }; env?: string;