@pagedip/lib-license-tools
Version:
242 lines (241 loc) • 9.23 kB
JavaScript
;
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