mirror of
https://github.com/marcogll/passkit-generator.git
synced 2026-03-15 19:25:23 +00:00
Reordered methods
This commit is contained in:
266
index.js
266
index.js
@@ -246,139 +246,6 @@ class Pass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if pass model type is one of the supported ones
|
|
||||||
*
|
|
||||||
* @method _validateType
|
|
||||||
* @params {Buffer} passBuffer - buffer of the pass structure content
|
|
||||||
* @returns {Boolean} true if type is supported, false otherwise.
|
|
||||||
*/
|
|
||||||
|
|
||||||
_validateType(passBuffer) {
|
|
||||||
let passTypes = ["boardingPass", "eventTicket", "coupon", "generic", "storeCard"];
|
|
||||||
|
|
||||||
try {
|
|
||||||
let passFile = JSON.parse(passBuffer.toString("utf8"));
|
|
||||||
let index = passTypes.findIndex(passType => passFile.hasOwnProperty(passType));
|
|
||||||
|
|
||||||
if (index == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let type = passTypes[index];
|
|
||||||
|
|
||||||
this.type = type;
|
|
||||||
return schema.isValid(passFile[type], schema.constants[(type === "boardingPass" ? "boarding" : "basic") + "Structure"]);
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the PKCS #7 cryptografic signature for the manifest file.
|
|
||||||
*
|
|
||||||
* @method _sign
|
|
||||||
* @params {String|Object} manifest - Manifest content.
|
|
||||||
* @returns {Buffer}
|
|
||||||
*/
|
|
||||||
|
|
||||||
_sign(manifest) {
|
|
||||||
let signature = forge.pkcs7.createSignedData();
|
|
||||||
|
|
||||||
if (typeof manifest === "object") {
|
|
||||||
signature.content = forge.util.createBuffer(JSON.stringify(manifest), "utf8");
|
|
||||||
} else if (typeof manifest === "string") {
|
|
||||||
signature.content = manifest;
|
|
||||||
} else {
|
|
||||||
throw new Error(errors.MANIFEST_TYPE.replace("%s", typeof manifest));
|
|
||||||
}
|
|
||||||
|
|
||||||
signature.addCertificate(this.Certificates.wwdr);
|
|
||||||
signature.addCertificate(this.Certificates.signerCert);
|
|
||||||
|
|
||||||
signature.addSigner({
|
|
||||||
key: this.Certificates.signerKey,
|
|
||||||
certificate: this.Certificates.signerCert,
|
|
||||||
digestAlgorithm: forge.pki.oids.sha1,
|
|
||||||
authenticatedAttributes: [{
|
|
||||||
type: forge.pki.oids.contentType,
|
|
||||||
value: forge.pki.oids.data
|
|
||||||
}, {
|
|
||||||
type: forge.pki.oids.messageDigest,
|
|
||||||
}, {
|
|
||||||
// the value is autogenerated
|
|
||||||
type: forge.pki.oids.signingTime,
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
|
|
||||||
signature.sign();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Signing creates in contentInfo a JSON object nested BER/TLV (X.690 standard) structure.
|
|
||||||
* Each object represents a component of ASN.1 (Abstract Syntax Notation)
|
|
||||||
* For a more complete reference, refer to: https://en.wikipedia.org/wiki/X.690#BER_encoding
|
|
||||||
*
|
|
||||||
* signature.contentInfo.type => SEQUENCE OF (16)
|
|
||||||
* signature.contentInfo.value[0].type => OBJECT IDENTIFIER (6)
|
|
||||||
* signature.contantInfo.value[1].type => END OF CONTENT (EOC - 0)
|
|
||||||
*
|
|
||||||
* EOC are only present only in constructed indefinite-length methods
|
|
||||||
* Since `signature.contentInfo.value[1].value` contains an object whose value contains the content we passed,
|
|
||||||
* we have to pop the whole object away to avoid signature content invalidation.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
signature.contentInfo.value.pop();
|
|
||||||
|
|
||||||
// Converting the JSON Structure into a DER (which is a subset of BER), ASN.1 valid structure
|
|
||||||
// Returning the buffer of the signature
|
|
||||||
|
|
||||||
return Buffer.from(forge.asn1.toDer(signature.toAsn1()).getBytes(), "binary");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edits the buffer of pass.json based on the passed options.
|
|
||||||
*
|
|
||||||
* @method _patch
|
|
||||||
* @params {Object} options - options resulting from the filtering made by filterPassOptions function
|
|
||||||
* @params {Buffer} passBuffer - Buffer of the contents of pass.json
|
|
||||||
* @returns {Promise<Buffer>} Edited pass.json buffer or Object containing error.
|
|
||||||
*/
|
|
||||||
|
|
||||||
_patch(passBuffer) {
|
|
||||||
if (!Object.keys(this.props).length) {
|
|
||||||
return Promise.resolve(passBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
const rgbValues = ["backgroundColor", "foregroundColor", "labelColor"];
|
|
||||||
let passFile = JSON.parse(passBuffer.toString("utf8"));
|
|
||||||
|
|
||||||
rgbValues.filter(v => this.props[v] && !isValidRGB(this.props[v])).forEach(v => delete this.props[v]);
|
|
||||||
|
|
||||||
if (this.shouldOverwrite) {
|
|
||||||
Object.assign(passFile, this.props);
|
|
||||||
} else {
|
|
||||||
Object.keys(this.props).forEach(prop => {
|
|
||||||
if (passFile[prop]) {
|
|
||||||
if (passFile[prop] instanceof Array) {
|
|
||||||
passFile[prop].push(...this.props[prop]);
|
|
||||||
} else if (passFile[prop] instanceof Object) {
|
|
||||||
Object.assign(passFile[prop], this.props[prop]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
passFile[prop] = this.props[prop];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fields.areas.forEach(area => {
|
|
||||||
if (this[area].fields.length) {
|
|
||||||
passFile[this.type][area].push(...this[area].fields);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.resolve(Buffer.from(JSON.stringify(passFile)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds barcodes to "barcode" and "barcodes" properties.
|
* Adds barcodes to "barcode" and "barcodes" properties.
|
||||||
* It will let later to add the missing versions
|
* It will let later to add the missing versions
|
||||||
@@ -524,6 +391,139 @@ class Pass {
|
|||||||
return types.map(T => (Object.assign({ format: T }, source)));
|
return types.map(T => (Object.assign({ format: T }, source)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if pass model type is one of the supported ones
|
||||||
|
*
|
||||||
|
* @method _validateType
|
||||||
|
* @params {Buffer} passBuffer - buffer of the pass structure content
|
||||||
|
* @returns {Boolean} true if type is supported, false otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_validateType(passBuffer) {
|
||||||
|
let passTypes = ["boardingPass", "eventTicket", "coupon", "generic", "storeCard"];
|
||||||
|
|
||||||
|
try {
|
||||||
|
let passFile = JSON.parse(passBuffer.toString("utf8"));
|
||||||
|
let index = passTypes.findIndex(passType => passFile.hasOwnProperty(passType));
|
||||||
|
|
||||||
|
if (index == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let type = passTypes[index];
|
||||||
|
|
||||||
|
this.type = type;
|
||||||
|
return schema.isValid(passFile[type], schema.constants[(type === "boardingPass" ? "boarding" : "basic") + "Structure"]);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the PKCS #7 cryptografic signature for the manifest file.
|
||||||
|
*
|
||||||
|
* @method _sign
|
||||||
|
* @params {String|Object} manifest - Manifest content.
|
||||||
|
* @returns {Buffer}
|
||||||
|
*/
|
||||||
|
|
||||||
|
_sign(manifest) {
|
||||||
|
let signature = forge.pkcs7.createSignedData();
|
||||||
|
|
||||||
|
if (typeof manifest === "object") {
|
||||||
|
signature.content = forge.util.createBuffer(JSON.stringify(manifest), "utf8");
|
||||||
|
} else if (typeof manifest === "string") {
|
||||||
|
signature.content = manifest;
|
||||||
|
} else {
|
||||||
|
throw new Error(errors.MANIFEST_TYPE.replace("%s", typeof manifest));
|
||||||
|
}
|
||||||
|
|
||||||
|
signature.addCertificate(this.Certificates.wwdr);
|
||||||
|
signature.addCertificate(this.Certificates.signerCert);
|
||||||
|
|
||||||
|
signature.addSigner({
|
||||||
|
key: this.Certificates.signerKey,
|
||||||
|
certificate: this.Certificates.signerCert,
|
||||||
|
digestAlgorithm: forge.pki.oids.sha1,
|
||||||
|
authenticatedAttributes: [{
|
||||||
|
type: forge.pki.oids.contentType,
|
||||||
|
value: forge.pki.oids.data
|
||||||
|
}, {
|
||||||
|
type: forge.pki.oids.messageDigest,
|
||||||
|
}, {
|
||||||
|
// the value is autogenerated
|
||||||
|
type: forge.pki.oids.signingTime,
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
signature.sign();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signing creates in contentInfo a JSON object nested BER/TLV (X.690 standard) structure.
|
||||||
|
* Each object represents a component of ASN.1 (Abstract Syntax Notation)
|
||||||
|
* For a more complete reference, refer to: https://en.wikipedia.org/wiki/X.690#BER_encoding
|
||||||
|
*
|
||||||
|
* signature.contentInfo.type => SEQUENCE OF (16)
|
||||||
|
* signature.contentInfo.value[0].type => OBJECT IDENTIFIER (6)
|
||||||
|
* signature.contantInfo.value[1].type => END OF CONTENT (EOC - 0)
|
||||||
|
*
|
||||||
|
* EOC are only present only in constructed indefinite-length methods
|
||||||
|
* Since `signature.contentInfo.value[1].value` contains an object whose value contains the content we passed,
|
||||||
|
* we have to pop the whole object away to avoid signature content invalidation.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
signature.contentInfo.value.pop();
|
||||||
|
|
||||||
|
// Converting the JSON Structure into a DER (which is a subset of BER), ASN.1 valid structure
|
||||||
|
// Returning the buffer of the signature
|
||||||
|
|
||||||
|
return Buffer.from(forge.asn1.toDer(signature.toAsn1()).getBytes(), "binary");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edits the buffer of pass.json based on the passed options.
|
||||||
|
*
|
||||||
|
* @method _patch
|
||||||
|
* @params {Object} options - options resulting from the filtering made by filterPassOptions function
|
||||||
|
* @params {Buffer} passBuffer - Buffer of the contents of pass.json
|
||||||
|
* @returns {Promise<Buffer>} Edited pass.json buffer or Object containing error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_patch(passBuffer) {
|
||||||
|
if (!Object.keys(this.props).length) {
|
||||||
|
return Promise.resolve(passBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rgbValues = ["backgroundColor", "foregroundColor", "labelColor"];
|
||||||
|
let passFile = JSON.parse(passBuffer.toString("utf8"));
|
||||||
|
|
||||||
|
rgbValues.filter(v => this.props[v] && !isValidRGB(this.props[v])).forEach(v => delete this.props[v]);
|
||||||
|
|
||||||
|
if (this.shouldOverwrite) {
|
||||||
|
Object.assign(passFile, this.props);
|
||||||
|
} else {
|
||||||
|
Object.keys(this.props).forEach(prop => {
|
||||||
|
if (passFile[prop]) {
|
||||||
|
if (passFile[prop] instanceof Array) {
|
||||||
|
passFile[prop].push(...this.props[prop]);
|
||||||
|
} else if (passFile[prop] instanceof Object) {
|
||||||
|
Object.assign(passFile[prop], this.props[prop]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
passFile[prop] = this.props[prop];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fields.areas.forEach(area => {
|
||||||
|
if (this[area].fields.length) {
|
||||||
|
passFile[this.type][area].push(...this[area].fields);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.resolve(Buffer.from(JSON.stringify(passFile)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters the options received in the query from http request into supported options
|
* Filters the options received in the query from http request into supported options
|
||||||
* by Apple and this application.
|
* by Apple and this application.
|
||||||
|
|||||||
Reference in New Issue
Block a user