strong-license
Advanced tools
Comparing version 1.0.2 to 1.1.0
@@ -1,4 +0,20 @@ | ||
2015-01-13, Version 1.0.2 | ||
2015-05-13, Version 1.1.0 | ||
========================= | ||
* ensure features list is coerced to an array (Ryan Graham) | ||
* add malformed license tests (Ryan Graham) | ||
* test: separate tests for API versions (Ryan Graham) | ||
* Expose License as module.License (Ryan Graham) | ||
* refactor License into its own module (Ryan Graham) | ||
* test: switch from tapsert to tap (Ryan Graham) | ||
2015-01-12, Version 1.0.2 | ||
========================= | ||
* Fix bad CLA URL in CONTRIBUTING.md (Ryan Graham) | ||
@@ -5,0 +21,0 @@ |
129
index.js
@@ -1,130 +0,7 @@ | ||
var fmt = require('util').format; | ||
var jwt = require('jwt-simple'); | ||
var License = require('./lib/license'); | ||
// TODO: remove top level exports in 2.x | ||
module.exports = License; | ||
module.exports.License = License; | ||
License.defaultSecret = 'strong-license'; | ||
License.defaultAlgorithm = 'HS256'; | ||
/** | ||
* License extends the JWT (JSON Web Token) format by adding additional fields, | ||
* defining a wildcard semantic for some fields, defining semantics for | ||
* validation against a query. | ||
* @class | ||
* @param {(string|Object)} input Encoded license string or license description object | ||
* @param {string} [secret] Secret to use for encoding/decoding the license | ||
* @param {string} [algorithm] Algorithm to encode/decode with | ||
*/ | ||
function License(input, secret, algorithm) { | ||
if (!(this instanceof License)) | ||
return new License(key); | ||
secret = secret || License.defaultSecret; | ||
algorithm = algorithm || License.defaultAlgorithm; | ||
if (typeof input === 'string' || input instanceof String) { | ||
this.key = input; | ||
this.details = normalized(safeDecode(input, secret)); | ||
} else { | ||
input = input || {}; | ||
this.details = normalized(input); | ||
this.key = jwt.encode(this.details, secret, algorithm); | ||
} | ||
} | ||
/** | ||
* @returns {Object} decoded object to stringify when serializing to JSON | ||
*/ | ||
License.prototype.toJSON = function LicenseToJSON() { | ||
return this.details; | ||
}; | ||
/** | ||
* @returns {string} decoded single-line string representation of a License | ||
*/ | ||
License.prototype.toString = function LicenseToString() { | ||
var lic = this.details; | ||
return fmt('License(email: %s, prod: %s, feat: %s, start: %s, end: %s)', | ||
lic.email, lic.product, lic.features.join(','), | ||
lic.activationDate, lic.expirationDate); | ||
}; | ||
/** | ||
* Licenses define a combination of product and features and the period of | ||
* time that the product and features are licensed for. | ||
* Parameters that are not given (or are otherwise falsey) do not have | ||
* requirements, so they always pass. If no arguments are given, then all | ||
* of the requirements are met and the scenario is considered "covered". | ||
* @param {string} [product] Product string to query license for | ||
* @param {string} [features] Feature string to query license for | ||
* @param {Date} [when] Point in time to test license against | ||
* @returns {Boolean} Whether the license covers the specified product, | ||
* feature, and time. | ||
*/ | ||
License.prototype.covers = function LicenseCovers(product, feature, when) { | ||
return (this.coversProduct(product) | ||
&& this.coversFeature(feature) | ||
&& this.coversDate(when)); | ||
}; | ||
/** | ||
* @param {string} [query] product string to test for | ||
* @returns {Boolean} true if query is falsey, identical to the product string | ||
* in the license, or if the product in the license is '*'. | ||
*/ | ||
License.prototype.coversProduct = function LicenseCoversProduct(query) { | ||
return match(this.details.product, query); | ||
}; | ||
/** | ||
* @param {string} [query] feature string to test for | ||
* @returns {Boolean} true if query is falsey, identical any string in the | ||
* license's feature list, or if the license's feature list | ||
* contains a '*'. | ||
*/ | ||
License.prototype.coversFeature = function LicenseCoversFeature(query) { | ||
return !query || this.details.features.some(function(enabled) { | ||
return match(enabled, query); | ||
}); | ||
}; | ||
/** | ||
* @param {Date} [when] point in time to test activation/expiration against | ||
* @returns {Boolean} true if when is falsey, or if it is between the | ||
* activationDate and expirationDate in the license. | ||
*/ | ||
License.prototype.coversDate = function LicenseCoversDate(when) { | ||
var lic = this.details; | ||
return !when || (lic.activationDate < when && lic.expirationDate > when); | ||
}; | ||
// 'foo' matches 'foo' | ||
// * matches anything | ||
// falsey query is matched by anything | ||
function match(pattern, query) { | ||
var result = !query || pattern === '*' || pattern === query; | ||
return result; | ||
} | ||
// Normalize input fields, defaulting to "invalid" or "expired" state where | ||
// details are missing. | ||
function normalized(input) { | ||
var l = JSON.parse(JSON.stringify(input)); | ||
l.userId = l.userId || null; | ||
l.email = l.email || null; | ||
l.product = l.product || null; | ||
l.features = l.features || []; | ||
l.activationDate = new Date(l.activationDate || 0); | ||
l.expirationDate = new Date(l.expirationDate || 0); | ||
return l; | ||
} | ||
function safeDecode(input, secret, algorithm) { | ||
try { | ||
return normalized(jwt.decode(input, secret, algorithm)); | ||
} catch (e) { | ||
return normalized({}); | ||
} | ||
} | ||
// If run directly, parse each argument as a license and dump its contents | ||
@@ -131,0 +8,0 @@ if (module === require.main) { |
{ | ||
"name": "strong-license", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"description": "Simple license generator/validator using JWT.", | ||
@@ -10,6 +10,6 @@ "main": "index.js", | ||
"devDependencies": { | ||
"tapsert": "0.0.1" | ||
"tap": "^1.0.2" | ||
}, | ||
"scripts": { | ||
"test": "node test.js --tap" | ||
"test": "tap test/test-*" | ||
}, | ||
@@ -16,0 +16,0 @@ "repository": { |
@@ -28,3 +28,3 @@ strong-license | ||
```js | ||
var License = require('strong-license'); | ||
var License = require('strong-license').License; | ||
var details = { | ||
@@ -47,3 +47,3 @@ email: 'user@example.com', | ||
```js | ||
var License = require('strong-license'); | ||
var License = require('strong-license').License; | ||
var nullLicense = new License(); | ||
@@ -59,3 +59,3 @@ | ||
```js | ||
var License = require('strong-license'); | ||
var License = require('strong-license').License; | ||
var now = new Date(); | ||
@@ -62,0 +62,0 @@ var yesterday = new Date(Date.now() - 1000*60*60*24); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
20371
11
250
1