mirror of
https://github.com/marcogll/passkit-generator.git
synced 2026-03-15 18:25:24 +00:00
Changed name for input model as parameter;
Added Joi to validate input parameters schema; Removed old draft of Pass class; Removed completely the old way to load the configuration
This commit is contained in:
330
index.js
330
index.js
@@ -4,6 +4,8 @@ const forge = require("node-forge");
|
|||||||
const archiver = require("archiver");
|
const archiver = require("archiver");
|
||||||
const async = require("async");
|
const async = require("async");
|
||||||
const stream = require("stream");
|
const stream = require("stream");
|
||||||
|
const Joi = require("joi");
|
||||||
|
const settingSchema = require("./schema.js");
|
||||||
|
|
||||||
const supportedTypesOfPass = /(boardingPass|eventTicket|coupon|generic|storeCard)/i;
|
const supportedTypesOfPass = /(boardingPass|eventTicket|coupon|generic|storeCard)/i;
|
||||||
const Certificates = {
|
const Certificates = {
|
||||||
@@ -33,159 +35,14 @@ function capitalizeFirst(str) {
|
|||||||
return str[0].toUpperCase()+str.slice(1);
|
return str[0].toUpperCase()+str.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// class Pass {
|
|
||||||
// constructor(modelName, options) {
|
|
||||||
// if (!modelName) {
|
|
||||||
// throw new Error("A model is required. Provide in order to continue.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// this._model = path.resolve(modelName);
|
|
||||||
// this._compiled = false;
|
|
||||||
// this._l10n = [];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// _modelExists() {
|
|
||||||
// return !fs.accessSync(this._model);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// _fetchModel() {
|
|
||||||
// return new Promise((success, reject) => {
|
|
||||||
// fs.readdir(this._model, function(err, files) {
|
|
||||||
// if (err) {
|
|
||||||
// // should not even enter in _fetchModel since the check is made by _modelExists method.
|
|
||||||
// throw new Error("Seems like the previous check, this._modelExists(), failed.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Removing hidden files and folders
|
|
||||||
// let list = removeHiddenFiles(files).filter(f => !f.includes(".lproj"));
|
|
||||||
|
|
||||||
// if (!list.length) {
|
|
||||||
// return reject("Model provided matched but unitialized. Refer to https://apple.co/2IhJr0Q to fill the model correctly.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!list.includes("pass.json")) {
|
|
||||||
// return reject("I'm a teapot. How am I supposed to serve you pass without pass.json in the chosen model as tea without water?");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Getting only folders
|
|
||||||
// let folderList = files.filter(f => f.includes(".lproj"));
|
|
||||||
|
|
||||||
// // I may have (and I rathered) used async.concat to achieve this but it returns a list of filenames ordered by folder.
|
|
||||||
// // The problem rises when I have to understand which is the first file of a folder which is not the first one.
|
|
||||||
// // By doing this way, I get an Array of folder contents (which is an array too).
|
|
||||||
|
|
||||||
// let folderExtractors = folderList.map(f => function(callback) {
|
|
||||||
// let l10nPath = path.join(modelPath, f);
|
|
||||||
|
|
||||||
// fs.readdir(l10nPath, function(err, list) {
|
|
||||||
// if (err) {
|
|
||||||
// return callback(err, null);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let filteredFiles = removeHiddenFiles(list);
|
|
||||||
|
|
||||||
// if (!filteredFiles.length) {
|
|
||||||
// return callback(null, []);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// this._l10n.push(f.replace(".lproj", ""));
|
|
||||||
|
|
||||||
// return callback(null, filteredFiles);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// async.parallel(folderExtractors, function(err, listByFolder) {
|
|
||||||
// if (err) {
|
|
||||||
// return reject(err);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //listByFolder.forEach((folder, index) => list.push(...folder.map(f => path.join(folderList[index], f))));
|
|
||||||
|
|
||||||
// list.push(...listByFolder.reduce(function(accumulator, folder, index) {
|
|
||||||
// accumulator.push(...folder.map(f => path.join(folderList[index], f)));
|
|
||||||
// return accumulator;
|
|
||||||
// }, []));
|
|
||||||
|
|
||||||
// return success(listByFolder)
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// _patch(patches) {
|
|
||||||
// if (!patches) {
|
|
||||||
// return Promise.resolve();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return new Promise(function(done, reject) {
|
|
||||||
// try {
|
|
||||||
// let passFile = JSON.parse(this.content.toString("utf8"));
|
|
||||||
|
|
||||||
// for (prop in patches) {
|
|
||||||
// passFile[prop] = patches[prop];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// this.content = Buffer.from(passFile);
|
|
||||||
// return done();
|
|
||||||
// } catch(e) {
|
|
||||||
// return reject(e);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// _fetchBody() {
|
|
||||||
// return new Promise((success, reject) => {
|
|
||||||
// fs.readFile(path.resolve(Configuration.passModelsDir, `${this._model}.pass`, "pass.json"), {}, function _parsePassJSONBuffer(err, passStructBuffer) {
|
|
||||||
// if (err) {
|
|
||||||
// return reject("Unable to fetch pass body buffer.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// this.content = passStructBuffer;
|
|
||||||
// return success(null);
|
|
||||||
|
|
||||||
// // editPassStructure(filterPassOptions(options.overrides), passStructBuffer)
|
|
||||||
// // .then(function _afterJSONParse(passFileBuffer) {
|
|
||||||
// // manifest["pass.json"] = forge.md.sha1.create().update(passFileBuffer.toString("binary")).digest().toHex();
|
|
||||||
// // archive.append(passFileBuffer, { name: "pass.json" });
|
|
||||||
|
|
||||||
// // return passCallback(null);
|
|
||||||
// // })
|
|
||||||
// // .catch(function(err) {
|
|
||||||
// // return reject({
|
|
||||||
// // status: false,
|
|
||||||
// // error: {
|
|
||||||
// // message: `pass.json Buffer is not a valid buffer. Unable to continue.\n${err}`,
|
|
||||||
// // ecode: 418
|
|
||||||
// // }
|
|
||||||
// // });
|
|
||||||
// // });
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// generate() {
|
|
||||||
// if (this._compiled) {
|
|
||||||
// throw new Error("Cannot generate the pass again.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// this._compiled = !this._compiled;
|
|
||||||
|
|
||||||
// return new Promise((success, reject) => {
|
|
||||||
// if (this._modelExists()) {
|
|
||||||
// this._fetchModel().then((list) => {
|
|
||||||
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Pass {
|
class Pass {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.options = options
|
this.overrides = options.overrides || {};
|
||||||
|
this.Certificates = {};
|
||||||
|
this.handlers = {};
|
||||||
|
this.modelDirectory = null;
|
||||||
|
this._parseSettings(options)
|
||||||
|
.then(() => console.log("WAT IS", this))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,7 +54,7 @@ class Pass {
|
|||||||
|
|
||||||
generate() {
|
generate() {
|
||||||
return new Promise((success, reject) => {
|
return new Promise((success, reject) => {
|
||||||
if (!this.options.modelName || typeof this.options.modelName !== "string") {
|
if (!this.modelName || typeof this.modelName !== "string") {
|
||||||
return reject({
|
return reject({
|
||||||
status: false,
|
status: false,
|
||||||
error: {
|
error: {
|
||||||
@@ -207,7 +64,7 @@ class Pass {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let modelPath = path.resolve(Configuration.passModelsDir, `${this.options.modelName}.pass`);
|
let modelPath = path.resolve(this.modelDirectory, `${this.modelName}.pass`);
|
||||||
|
|
||||||
fs.readdir(modelPath, (err, files) => {
|
fs.readdir(modelPath, (err, files) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -273,8 +130,8 @@ class Pass {
|
|||||||
// Otherwise would had to put everything in editPassStructure's Promise .then().
|
// Otherwise would had to put everything in editPassStructure's Promise .then().
|
||||||
async.parallel([
|
async.parallel([
|
||||||
(passCallback) => {
|
(passCallback) => {
|
||||||
fs.readFile(path.resolve(Configuration.passModelsDir, `${this.options.modelName}.pass`, "pass.json"), {}, (err, passStructBuffer) => {
|
fs.readFile(path.resolve(this.modelDirectory, `${this.modelName}.pass`, "pass.json"), {}, (err, passStructBuffer) => {
|
||||||
this._patch(this._filterOptions(this.options.overrides), passStructBuffer)
|
this._patch(this._filterOptions(this.overrides), passStructBuffer)
|
||||||
.then(function _afterJSONParse(passFileBuffer) {
|
.then(function _afterJSONParse(passFileBuffer) {
|
||||||
manifest["pass.json"] = forge.md.sha1.create().update(passFileBuffer.toString("binary")).digest().toHex();
|
manifest["pass.json"] = forge.md.sha1.create().update(passFileBuffer.toString("binary")).digest().toHex();
|
||||||
archive.append(passFileBuffer, { name: "pass.json" });
|
archive.append(passFileBuffer, { name: "pass.json" });
|
||||||
@@ -301,11 +158,11 @@ class Pass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adding the files to the zip - i'm not using .directory method because it adds also hidden files like .DS_Store on macOS
|
// adding the files to the zip - i'm not using .directory method because it adds also hidden files like .DS_Store on macOS
|
||||||
archive.file(path.resolve(Configuration.passModelsDir, `${this.options.modelName}.pass`, file), { name: file });
|
archive.file(path.resolve(this.modelDirectory, `${this.modelName}.pass`, file), { name: file });
|
||||||
|
|
||||||
let hashFlow = forge.md.sha1.create();
|
let hashFlow = forge.md.sha1.create();
|
||||||
|
|
||||||
fs.createReadStream(path.resolve(Configuration.passModelsDir, `${this.options.modelName}.pass`, file))
|
fs.createReadStream(path.resolve(this.modelDirectory, `${this.modelName}.pass`, file))
|
||||||
.on("data", function(data) {
|
.on("data", function(data) {
|
||||||
hashFlow.update(data.toString("binary"));
|
hashFlow.update(data.toString("binary"));
|
||||||
})
|
})
|
||||||
@@ -369,12 +226,12 @@ class Pass {
|
|||||||
throw new Error(`Manifest content must be a string or an object. Unable to accept manifest of type ${typeof manifest}`);
|
throw new Error(`Manifest content must be a string or an object. Unable to accept manifest of type ${typeof manifest}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
signature.addCertificate(Certificates.wwdr);
|
signature.addCertificate(this.Certificates.wwdr);
|
||||||
signature.addCertificate(Certificates.signerCert);
|
signature.addCertificate(this.Certificates.signerCert);
|
||||||
|
|
||||||
signature.addSigner({
|
signature.addSigner({
|
||||||
key: Certificates.signerKey,
|
key: this.Certificates.signerKey,
|
||||||
certificate: Certificates.signerCert,
|
certificate: this.Certificates.signerCert,
|
||||||
digestAlgorithm: forge.pki.oids.sha1,
|
digestAlgorithm: forge.pki.oids.sha1,
|
||||||
authenticatedAttributes: [{
|
authenticatedAttributes: [{
|
||||||
type: forge.pki.oids.contentType,
|
type: forge.pki.oids.contentType,
|
||||||
@@ -494,99 +351,82 @@ class Pass {
|
|||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Validates the contents of the passed options and assigns the contents to the right properties
|
||||||
|
*/
|
||||||
|
|
||||||
function loadConfiguration(setup) {
|
_parseSettings(options) {
|
||||||
let reqFilesKeys = ["wwdr", "signerCert", "signerKey"];
|
return new Promise((success, reject) => {
|
||||||
|
// var contents = {
|
||||||
|
// "certificates": {
|
||||||
|
// "wwdr": "aaaa",
|
||||||
|
// "signer": {
|
||||||
|
// "cert": "aaaaa",
|
||||||
|
// "key": "aaaa"
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "handlers": {
|
||||||
|
// "barcode": function() { console.log("aaa"); }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
// Node-Forge also accepts .cer certificates
|
if (!settingSchema.validate(options)) {
|
||||||
if (!setup.certificates.dir || fs.accessSync(path.resolve(setup.certificates.dir)) !== undefined) {
|
throw new Error("The options passed to Pass constructor does not meet the requirements. Refer to the documentation to compile them correctly.")
|
||||||
throw new Error("Unable to load certificates directory. Check its existence or the permissions.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!setup.certificates.files) {
|
|
||||||
throw new Error("Expected key 'files' in configuration file but not found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!setup.certificates.files.wwdr) {
|
|
||||||
throw new Error("Expected file path or content for key certificates.files.wwdr. Please provide a valid certificate from https://apple.co/2sc2pvv");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!setup.certificates.files.signerCert) {
|
|
||||||
throw new Error("Expected file path or content for key certificates.files.signerCert. Please provide a valid signer certificate.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!setup.certificates.files.signerKey || !setup.certificates.credentials.privateKeySecret) {
|
|
||||||
throw new Error("Expected file path or content for key certificates.files.signerKey with an associated password at certificates.credentials.privateKeySecret but not found.")
|
|
||||||
}
|
|
||||||
|
|
||||||
let certPaths = reqFilesKeys.map(e => path.resolve(setup.certificates.dir, setup.certificates.files[e]));
|
|
||||||
|
|
||||||
return new Promise(function(success, reject) {
|
|
||||||
let docStruct = {};
|
|
||||||
|
|
||||||
async.concat(certPaths, fs.readFile, function(err, contents) {
|
|
||||||
if (err) {
|
|
||||||
return reject(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return success(
|
this.modelDirectory = path.resolve(__dirname, options.modelDir);
|
||||||
contents.map(function(file, index) {
|
this.Certificates.dir = options.certificates.dir;
|
||||||
if (file.includes("PRIVATE KEY")) {
|
this.modelName = options.modelName;
|
||||||
return forge.pki.decryptRsaPrivateKey(
|
|
||||||
file,
|
|
||||||
setup.certificates.credentials.privateKeySecret
|
|
||||||
);
|
|
||||||
} else if (file.includes("CERTIFICATE")) {
|
|
||||||
return forge.pki.certificateFromPem(file);
|
|
||||||
} else {
|
|
||||||
throw new Error("File not allowed in configuration. Only .pems files containing certificates and private keys are allowed");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function init(configPath) {
|
let certPaths = Object.keys(options.certificates).filter(v => v !== "dir").map((val) => {
|
||||||
if (Certificates.status) {
|
return path.resolve(this.Certificates.dir, typeof options.certificates[val] !== "object" ? options.certificates[val] : options.certificates[val]["keyFile"])
|
||||||
throw new Error("Initialization must be triggered only once.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!configPath || typeof configPath !== "object" || typeof configPath === "object" && !Object.keys(configPath).length) {
|
|
||||||
throw new Error(`Cannot initialize PassKit module. Param 0 expects a non-empty configuration object.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let queue = [
|
|
||||||
new Promise(function(success, reject) {
|
|
||||||
fs.access(path.resolve(configPath.models.dir), function(err) {
|
|
||||||
if (err) {
|
|
||||||
return reject("A valid pass model directory is required. Please provide one in the configuration file under voice 'models.dir'.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return success(true);
|
|
||||||
});
|
});
|
||||||
}),
|
|
||||||
loadConfiguration(configPath)
|
|
||||||
];
|
|
||||||
|
|
||||||
Promise.all(queue)
|
async.parallel([
|
||||||
.then(function(results) {
|
(function __certificatesParser(callback) {
|
||||||
let certs = results[1];
|
async.concat(certPaths, fs.readFile, (err, contents) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
if (results[0]) {
|
contents.forEach(file => {
|
||||||
Configuration.passModelsDir = configPath.models.dir;
|
let pem = this.__parsePEM(file, options.certificates.signerKey.passphrase);
|
||||||
|
if (!pem.key || !pem.value) {
|
||||||
|
throw new Error("Invalid certificates got loaded. Please provide WWDR certificates and developer signer certificate and key (with passphrase).");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Certificates[pem.key] = pem.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return callback();
|
||||||
|
});
|
||||||
|
}).bind(this),
|
||||||
|
|
||||||
|
(function __handlersAssign(callback) {
|
||||||
|
this.handlers = options.handlers || {};
|
||||||
|
return callback();
|
||||||
|
}).bind(this)
|
||||||
|
], success);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
__parsePEM(element, passphrase) {
|
||||||
|
if (element.includes("PRIVATE KEY") && !!passphrase) {
|
||||||
|
return {
|
||||||
|
key: "signerKey",
|
||||||
|
value: forge.pki.decryptRsaPrivateKey(element, String(passphrase))
|
||||||
|
};
|
||||||
|
} else if (element.includes("CERTIFICATE")) {
|
||||||
|
// PEM-exported certificates with keys are in PKCS#12 format, hence they are composed of bags.
|
||||||
|
return {
|
||||||
|
key: element.includes("Bag Attributes") ? "signerCert" : "wwdr",
|
||||||
|
value: forge.pki.certificateFromPem(element)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return { key: null, value: null };
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Certificates.wwdr = certs[0];
|
|
||||||
Certificates.signerCert = certs[1];
|
|
||||||
Certificates.signerKey = certs[2];
|
|
||||||
Certificates.status = true;
|
|
||||||
})
|
|
||||||
.catch(function(error) {
|
|
||||||
throw new Error(error);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { init, Pass };
|
module.exports = { Pass };
|
||||||
|
|||||||
36
package-lock.json
generated
36
package-lock.json
generated
@@ -313,6 +313,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
|
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
|
||||||
},
|
},
|
||||||
|
"hoek": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.3.tgz",
|
||||||
|
"integrity": "sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw=="
|
||||||
|
},
|
||||||
"http-errors": {
|
"http-errors": {
|
||||||
"version": "1.6.3",
|
"version": "1.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
||||||
@@ -353,6 +358,24 @@
|
|||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||||
},
|
},
|
||||||
|
"isemail": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/isemail/-/isemail-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-zfRhJn9rFSGhzU5tGZqepRSAj3+g6oTOHxMGGriWNJZzyLPUK8H7VHpqKntegnW8KLyGA9zwuNaCoopl40LTpg==",
|
||||||
|
"requires": {
|
||||||
|
"punycode": "2.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"joi": {
|
||||||
|
"version": "13.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/joi/-/joi-13.4.0.tgz",
|
||||||
|
"integrity": "sha512-JuK4GjEu6j7zr9FuVe2MAseZ6si/8/HaY0qMAejfDFHp7jcH4OKE937mIHM5VT4xDS0q7lpQbszbxKV9rm0yUg==",
|
||||||
|
"requires": {
|
||||||
|
"hoek": "5.x.x",
|
||||||
|
"isemail": "3.x.x",
|
||||||
|
"topo": "3.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"lazystream": {
|
"lazystream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
|
||||||
@@ -475,6 +498,11 @@
|
|||||||
"ipaddr.js": "1.6.0"
|
"ipaddr.js": "1.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"punycode": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||||
|
},
|
||||||
"qs": {
|
"qs": {
|
||||||
"version": "6.5.1",
|
"version": "6.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
|
||||||
@@ -611,6 +639,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
|
||||||
"integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
|
"integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
|
||||||
},
|
},
|
||||||
|
"topo": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/topo/-/topo-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tlu1fGlR90iCdIPURqPiufqAlCZYzLjHYVVbcFWDMcX7+tK8hdZWAfsMrD/pBul9jqHHwFjNdf1WaxA9vTRRhw==",
|
||||||
|
"requires": {
|
||||||
|
"hoek": "5.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"type-is": {
|
"type-is": {
|
||||||
"version": "1.6.16",
|
"version": "1.6.16",
|
||||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"archiver": "^2.1.1",
|
"archiver": "^2.1.1",
|
||||||
"async": "^2.6.0",
|
"async": "^2.6.0",
|
||||||
"express": "^4.16.3",
|
"express": "^4.16.3",
|
||||||
|
"joi": "^13.4.0",
|
||||||
"node-forge": "^0.7.5"
|
"node-forge": "^0.7.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
server.js
12
server.js
@@ -4,8 +4,6 @@ const fs = require("fs");
|
|||||||
const Passkit = require("./index");
|
const Passkit = require("./index");
|
||||||
const Configuration = require("./config.json");
|
const Configuration = require("./config.json");
|
||||||
|
|
||||||
Passkit.init(Configuration);
|
|
||||||
|
|
||||||
const instance = express();
|
const instance = express();
|
||||||
|
|
||||||
instance.use(express.json());
|
instance.use(express.json());
|
||||||
@@ -31,7 +29,17 @@ function manageRequest(request, response) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let pass = new Passkit.Pass({
|
let pass = new Passkit.Pass({
|
||||||
|
modelDir: "passModels/",
|
||||||
modelName: request.params.modelName || request.query.modelName,
|
modelName: request.params.modelName || request.query.modelName,
|
||||||
|
certificates: {
|
||||||
|
dir: "certificates/",
|
||||||
|
wwdr: "WWDR.pem",
|
||||||
|
signerCert: "passcertificate.pem",
|
||||||
|
signerKey: {
|
||||||
|
keyFile: "passkey.pem",
|
||||||
|
passphrase: "123456"
|
||||||
|
}
|
||||||
|
},
|
||||||
overrides: {}
|
overrides: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user