diff --git a/index.js b/index.js index 2ac6844..6ee0434 100644 --- a/index.js +++ b/index.js @@ -542,25 +542,6 @@ class Pass { return Buffer.from(JSON.stringify(passFile)); } - /** - * Filters the options received in the query from http request into supported options - * by Apple and this application. - * - * @method _filterOptions - * @params {Object} opts - raw informations to be edited in the pass.json file - * from HTTP Request Params or Body - * @returns {Object} - filtered options based on above criterias. - */ - - _filterOptions(opts) { - const forbidden = ["primaryFields", "secondaryFields", "auxiliaryFields", "backFields", "headerFields", "expirationDate", "voided", "locations", "beacons", "maxDistance", "relevantDate"]; - const supported = ["serialNumber", "userInfo", "authenticationToken", "barcode", "backgroundColor", "foregroundColor", "labelColor"]; - - let valid = Object.keys(opts).filter(o => !forbidden.includes(o) && supported.includes(o)); - - return Object.assign(...valid.map(v => ({ [v]: opts[v] })), {}); - } - /** * Validates the contents of the passed options and assigns the contents to the right properties * @@ -581,7 +562,9 @@ class Pass { this.model = path.resolve(options.model) + (!!options.model && !path.extname(options.model) ? ".pass" : ""); - Object.assign(this.props, this._filterOptions(options.overrides)); + const filteredOpts = schema.filter(options, schema.constants.supportedOptions); + + Object.assign(this.props, filteredOpts); let optCertsNames = Object.keys(options.certificates); diff --git a/schema.js b/schema.js index 4e2fbd6..2b4eb33 100644 --- a/schema.js +++ b/schema.js @@ -15,6 +15,22 @@ let instance = Joi.object().keys({ shouldOverwrite: Joi.boolean() }); +let supportedOptions = Joi.object().keys({ + serialNumber: Joi.string(), + userInfo: Joi.alternatives(Joi.object().unknown(), Joi.array()), + webServiceURL: Joi.string().regex(/^https?:\/\/(?:[a-z0-9]+\.[a-z0-9]+\.[a-z]+(?:\.[a-z]+)?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/?(?:[a-z\/_%0-9A-Z.]+)?/), + authenticationToken: Joi.when("webServiceURL", { + is: Joi.exist(), + then: Joi.string().token().min(16).required(), + otherwise: Joi.string().token().min(16) + }), + backgroundColor: Joi.string().min(10).max(16), + foregroundColor: Joi.string().min(10).max(16), + labelColor: Joi.string().min(10).max(16), + groupingIdentifier: Joi.string(), + suppressStripShine: Joi.boolean() +}); + let barcode = Joi.object().keys({ altText: Joi.string(), messageEncoding: Joi.string().default("iso-8859-1").required(), @@ -56,6 +72,37 @@ let passDict = Joi.object().keys({ let transitType = Joi.string().regex(/(PKTransitTypeAir|PKTransitTypeBoat|PKTransitTypeBus|PKTransitTypeGeneric|PKTransitTypeTrain)/); +let nfcDict = Joi.object().keys({ + message: Joi.string().required().max(64), + encryptionPublicKey: Joi.string() +}); + +let isValid = (opts, schemaName) => { + let validation = Joi.validate(opts, schemaName); + + if (validation.error) { + debug(`validation failed due to error: ${validation.error.message}`); + } + + return !validation.error; +}; + +let filter = (opts, schemaName) => { + let isObject = opts instanceof Object; + let list = isObject ? Object.keys(opts) : opts; + + return list.reduce((acc, current, index) => { + let ref = isObject ? current : index; + let check = isObject ? { [current] : opts[current] } : [ opts[index] ]; + + if (isValid(check, schemaName)) { + acc[ref] = opts[ref]; + } + + return acc; + }, isObject ? {} : []); +} + module.exports = { constants: { instance, @@ -64,15 +111,10 @@ module.exports = { passDict, beaconsDict, locationsDict, - transitType + transitType, + nfcDict, + supportedOptions }, - isValid: (opts, schemaName) => { - let validation = Joi.validate(opts, schemaName); - - if (validation.error) { - debug(`validation failed due to error: ${validation.error.message}`); - } - - return !validation.error; - } + isValid, + filter };