UNPKG

@pagedip/lib-license-tools

Version:
242 lines (241 loc) 9.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const path_1 = require("path"); const find_up_1 = tslib_1.__importDefault(require("find-up")); const fs_1 = tslib_1.__importDefault(require("mz/fs")); const child_process_1 = require("mz/child_process"); const url_1 = require("url"); const node_fetch_1 = tslib_1.__importDefault(require("node-fetch")); const util_1 = require("util"); const jsonwebtoken_1 = tslib_1.__importDefault(require("jsonwebtoken")); const util_logger_1 = tslib_1.__importDefault(require("@pagedip/util-logger")); const lib_license_errors_1 = require("@pagedip/lib-license-errors"); const win = process.platform === "win32"; const home = (win ? process.env.USERPROFILE : process.env.HOME) || ""; const licenseServerUrl = "https://license.system.pagedip.com"; const licenseServerHost = (() => { const url = new url_1.URL(licenseServerUrl); return url.host; })(); /** Main file path for the pdlicense file. Depends on platform. */ exports.installPath = home ? path_1.join(home, ".pdlicense") : path_1.join(win ? "/etc" : "/usr/local/etc", "pdlicense"); const licenseFiles = [path_1.join("/etc", "pdlicense"), path_1.join("/usr/local/etc", "pdlicense"), path_1.join(home, ".pdlicense")]; var LicenseData; (function (LicenseData) { function is(v) { return (Boolean(v) && typeof v.original === "string" && Boolean(v.original) && typeof v.id === "string" && Boolean(v.id) && typeof v.user === "string" && Boolean(v.user) && typeof v.payload === "object" && v.payload != null && typeof v.revoked === "boolean" && typeof v.expired === "boolean" && util_1.isDate(v.ttl) && !isNaN(v.ttl) && util_1.isDate(v.issued) && !isNaN(v.issued)); } LicenseData.is = is; })(LicenseData = exports.LicenseData || (exports.LicenseData = {})); /** * Attempts to locate the raw license string on the system. First, it directly returns any license passed as an * argument. Next, it checks the `pagedip_license` environment variable. Lastly, it checks known file paths for a * pdlicense file. */ function findLicenseString(license) { if (license) return license; if (process.env.pagedip_license) return process.env.pagedip_license; let file = find_up_1.default.sync(".pdlicense"); if (!file) for (let i = 0; i < licenseFiles.length; i++) { try { const stat = fs_1.default.statSync(licenseFiles[i]); if (stat.isFile()) { file = licenseFiles[i]; break; } } catch (e) { continue; } } if (file) { return fs_1.default.readFileSync(file, "utf-8").trim(); } } exports.findLicenseString = findLicenseString; /** * Checks a license string against the license server and returns the results. */ async function verify(license) { if (!license) { throw new lib_license_errors_1.LicenseMissingError(); } const resp = await node_fetch_1.default(`${licenseServerUrl}/license/verify`, { method: "POST", headers: { "Content-Type": "text/plain; charset=utf-8", }, body: license, }); let body; try { body = await resp.json(); } catch (e) { throw new lib_license_errors_1.LicenseInvalidError("Invalid response from license server."); } if (!resp.ok || !body.ok) { if (body.error) { throw new lib_license_errors_1.PagedipError(body); } else { throw new lib_license_errors_1.LicenseUnknownError(); } } const { id, user, payload, revoked, expired, ttl, issued } = body; const result = { id, user, payload, revoked, expired, ttl: ttl ? new Date(ttl) : undefined, issued: issued ? new Date(issued) : undefined, original: license, }; if (!LicenseData.is(result)) { throw new lib_license_errors_1.LicenseInvalidError("License result had an incorrect format."); } return result; } exports.verify = verify; /** Find and verifies the license in one step. */ async function findAndVerify(license = findLicenseString()) { if (!license) { throw new lib_license_errors_1.LicenseMissingError(); } return verify(license); } exports.findAndVerify = findAndVerify; /** Install a license string onto the file system and setup NPM to use the license server registry. */ async function install(license) { if (!license) { throw new lib_license_errors_1.LicenseMissingError(); } await fs_1.default.writeFile(exports.installPath, license); await child_process_1.exec(`npm config set @pagedip:registry ${licenseServerUrl}/npm/`); await child_process_1.exec(`npm config set @beneaththeink:registry ${licenseServerUrl}/npm/`); await child_process_1.exec(`npm config set //${licenseServerHost}/npm/:_authToken ${license}`); } exports.install = install; /** Inverse of install(), this will remove the license file and remove license server NPM configuration. */ async function uninstall() { await child_process_1.exec(`npm config delete @pagedip:registry`); await child_process_1.exec(`npm config delete @beneaththeink:registry`); await child_process_1.exec(`npm config delete //${licenseServerHost}/:_authToken`); await child_process_1.exec(`npm config delete //${licenseServerHost}/npm/:_authToken`); try { await fs_1.default.unlink(exports.installPath); } catch (e) { if (e.code !== "ENOENT") throw e; } } exports.uninstall = uninstall; const publicKeys = [ `-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApOGsKsYBfJAcXp7uIvz3 WgbyIEhus+bjO1EAoKrudbSBA/zaBd0d9Og51icfqQGjJ4KLv4KoYMj6cJCmaQw1 ChxFbUTSG1FEsIzNSApiKXnxRTecblB9177zgLBNRtwHg2Ko7YKtBkyBlJu2qBnN ok5Vms676RZzKo+CBL9sfdKkD0rt8TLfsCQRRACxDoRYxeeCU4ZOTAJgsQTsD1bI eoOBBD8YbksMYA/vCYDfcIBeAYbLPIaLtj4V3aUWu5++MWLkehmAxf/3WdTNyfEB bJ3DJv15/bh+JewU/jsDBcgPEiMvRoWgCOQ4UGu9XPq5TU3QZRkJBBqU/YrWE5k4 NrqaozhvknoLBdxiIl5dhnLuZ//MBzHsuIJTMhKCiB76llM+XIWn0rXh+mQ1vsri Y09Ua2yabJYF30VM6Xr2lpD7x5hcoKIbTPFna+Fcv+M4TwwP9LFdXh5ORQz9DEYC ftQnaUBcZzpiyvawWincP7A8MQU3udz3Wn5gGDr3AZ8CifRChI2jP4Y4WQPi+X9R Ud+Z1opGudiPVC41U2YypfYtZipkAwISTt26qDfNQ50ZzbbGlDQ8alUf6XyRXhXZ lmZ3XW+e+GwLHmP1tthEb9FSc3asM09V4WZ3wc5GlZfeEkZYc32vUdHgIgFnBOwy QFFWXF6/VNUs7soEfoYUc50CAwEAAQ== -----END PUBLIC KEY-----`, ]; /** Similar to verify(), but does the verification without network requests using known license server public keys. */ function verifyOffline(license) { if (!license) { throw new lib_license_errors_1.LicenseMissingError(); } let data; for (let i = 0; i < publicKeys.length; i++) { try { const decoded = jsonwebtoken_1.default.verify(license, publicKeys[i], { algorithms: ["RS256"], }); if (typeof decoded === "object" && decoded != null) { data = decoded; break; } } catch (e) { if (e.message.match(/jwt expired/i)) { throw new lib_license_errors_1.LicenseExpiredError(); } if (!e.message.match(/invalid signature/i)) { throw e; } } } if (!data) { throw new lib_license_errors_1.LicenseInvalidError("License signature is invalid."); } const { exp, iat, aud, sub, iss } = data, payload = tslib_1.__rest(data, ["exp", "iat", "aud", "sub", "iss"]); const result = { id: sub, user: aud, payload, revoked: false, expired: false, ttl: exp ? new Date(exp * 1000) : undefined, issued: iat ? new Date(iat * 1000) : undefined, original: license, }; if (!LicenseData.is(result)) { throw new lib_license_errors_1.LicenseInvalidError("License result had an incorrect format."); } return result; } exports.verifyOffline = verifyOffline; /** Find and verifies the license offline in one step. */ function findAndVerifyOffline(license = findLicenseString()) { if (!license) { throw new lib_license_errors_1.LicenseMissingError(); } return verifyOffline(license); } exports.findAndVerifyOffline = findAndVerifyOffline; /** Print license data in a human friendly format. */ function print(data, opts = {}) { const { colors = true } = opts; if (LicenseData.is(data)) { const msg = "Valid Pagedip license key."; return `${colors ? util_logger_1.default.color.white.bgGreen(msg) : msg} ID: ${data.id} Registered To: ${data.user} Issued: ${data.issued.toLocaleString()} Expires: ${data.issued.toLocaleString()} ${util_1.inspect(data.payload, { colors, depth: Infinity })}`; } else { const msg = "Invalid Pagedip license key."; return colors ? util_logger_1.default.color.white.bgRed(msg) : msg; } } exports.print = print; //# sourceMappingURL=index.js.map