{"version":3,"file":"license.mjs","sources":["../../src/ee/license.ts"],"sourcesContent":["import fs from 'fs';\nimport { join, resolve } from 'path';\nimport crypto from 'crypto';\nimport type { Core } from '@strapi/types';\n\nimport { generateInstallId } from '@strapi/utils';\n\ninterface LicenseInfo {\n  type: 'bronze' | 'silver' | 'gold';\n  isTrial: boolean;\n  expireAt?: string;\n  seats?: number;\n  features?: Array<{ name: string; options?: Record<string, unknown> }>;\n}\n\nconst DEFAULT_FEATURES = {\n  bronze: [],\n  silver: [],\n  gold: [\n    { name: 'sso' },\n    // Set a null retention duration to allow the user to override it\n    // The default of 90 days is set in the audit logs service\n    { name: 'audit-logs', options: { retentionDays: null } },\n    { name: 'review-workflows' },\n    { name: 'cms-content-releases' },\n    { name: 'cms-content-history', options: { retentionDays: 99999 } },\n    { name: 'cms-advanced-preview' },\n  ],\n};\n\nconst LICENSE_REGISTRY_URI = 'https://license.strapi.io';\n\nconst publicKey = fs.readFileSync(resolve(__dirname, '../../resources/key.pub'));\n\nclass LicenseCheckError extends Error {\n  shouldFallback = false;\n\n  constructor(message: string, shouldFallback = false) {\n    super(message);\n\n    this.shouldFallback = shouldFallback;\n  }\n}\n\nconst readLicense = (directory: string) => {\n  try {\n    const path = join(directory, 'license.txt');\n    return fs.readFileSync(path).toString();\n  } catch (error) {\n    if (typeof error === 'object' && error !== null && 'code' in error && error.code !== 'ENOENT') {\n      throw Error('License file not readable, review its format and access rules.');\n    }\n  }\n};\n\nconst verifyLicense = (license: string) => {\n  const [signature, base64Content] = Buffer.from(license, 'base64').toString().split('\\n');\n\n  if (!signature || !base64Content) {\n    throw new Error('Invalid license.');\n  }\n\n  const stringifiedContent = Buffer.from(base64Content, 'base64').toString();\n\n  const verify = crypto.createVerify('RSA-SHA256');\n  verify.update(stringifiedContent);\n  verify.end();\n\n  const verified = verify.verify(publicKey, signature, 'base64');\n\n  if (!verified) {\n    throw new Error('Invalid license.');\n  }\n\n  const licenseInfo: LicenseInfo = JSON.parse(stringifiedContent);\n\n  if (!licenseInfo.features) {\n    licenseInfo.features = DEFAULT_FEATURES[licenseInfo.type];\n  }\n\n  if (!licenseInfo.isTrial) {\n    licenseInfo.isTrial = false;\n  }\n\n  Object.freeze(licenseInfo.features);\n  return licenseInfo;\n};\n\nconst throwError = () => {\n  throw new LicenseCheckError('Could not proceed to the online validation of your license.', true);\n};\n\nconst fetchLicense = async (\n  { strapi }: { strapi: Core.Strapi },\n  key: string,\n  projectId: string\n) => {\n  const { installId: installIdFromPackageJson } = strapi.config;\n\n  const response = await strapi\n    .fetch(`${LICENSE_REGISTRY_URI}/api/licenses/validate`, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({\n        key,\n        projectId,\n        deviceId: generateInstallId(projectId, installIdFromPackageJson),\n      }), // NOTE: Doing nothing on the LR with the installId\n    })\n    .catch(throwError);\n\n  const contentType = response.headers.get('Content-Type');\n\n  if (contentType?.includes('application/json')) {\n    const { data, error } = await response.json();\n\n    switch (response.status) {\n      case 200:\n        return data.license;\n      case 400:\n        throw new LicenseCheckError(error.message);\n      case 404:\n        throw new LicenseCheckError('The license used does not exists.');\n      default:\n        throwError();\n    }\n  } else {\n    throwError();\n  }\n};\n\nexport { readLicense, verifyLicense, fetchLicense, LicenseCheckError, LICENSE_REGISTRY_URI };\n"],"names":["DEFAULT_FEATURES","bronze","silver","gold","name","options","retentionDays","LICENSE_REGISTRY_URI","publicKey","fs","readFileSync","resolve","__dirname","LicenseCheckError","Error","message","shouldFallback","readLicense","directory","path","join","toString","error","code","verifyLicense","license","signature","base64Content","Buffer","from","split","stringifiedContent","verify","crypto","createVerify","update","end","verified","licenseInfo","JSON","parse","features","type","isTrial","Object","freeze","throwError","fetchLicense","strapi","key","projectId","installId","installIdFromPackageJson","config","response","fetch","method","headers","body","stringify","deviceId","generateInstallId","catch","contentType","get","includes","data","json","status"],"mappings":"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"}