diff --git a/src/flags.js b/src/flags.js index 0cac932b..ada0dd7b 100644 --- a/src/flags.js +++ b/src/flags.js @@ -4,41 +4,46 @@ const ROLE_ADMIN = 'admin' const ROLE_AGENT = 'agent' /** ORDER FLAGS (Commerce Provider) **/ -const FLAG_ORDER_HISTORY = 'order_history' -const FLAG_ORDER_DETAILS = 'order_details' -const FLAG_ORDER_FILTER = 'order_filter' -const FLAG_ORDER_PIN = 'order_pin' -const FLAG_ORDER_SORT = 'order_sort' -const FLAG_ORDER_PAYMENT = 'order_payment' -const FLAG_ORDER_REFUND = 'order_refund' -const FLAG_ORDER_CREATE = 'order_create' -const FLAG_ORDER_DUPLICATE = 'order_duplicate' -const FLAG_ORDER_MODIFY = 'order_modify' +const FLAG_ORDERS_LIST = 'orders_list' // FREE +const FLAG_ORDER_DETAILS = 'order_details' // FREE + +const FLAG_ORDER_FILTER = 'order_filter' // STARTER +const FLAG_ORDER_PIN = 'order_pin' // STARTER +const FLAG_ORDER_SORT = 'order_sort' // STARTER + +const FLAG_ORDER_TIMELINE = 'order_timeline' // PROFESIONAL + +const FLAG_ORDER_PAYMENT = 'order_payment' // ENTERPRISE +const FLAG_ORDER_REFUND = 'order_refund' // ENTERPRISE +const FLAG_ORDER_CREATE = 'order_create' // ENTERPRISE +const FLAG_ORDER_DUPLICATE = 'order_duplicate' // ENTERPRISE +const FLAG_ORDER_MODIFY = 'order_modify' // ENTERPRISE /** PAYMENT FLAGS (Payment or Commerce Provider) **/ -const FLAG_PAYMENT_TRANSACTIONS = 'payment_transactions' +const FLAG_PAYMENT_TRANSACTIONS = 'payment_transactions' // PROFESSIONAL const FLAG_PAYMENT_USER_INTERFACE = 'payment_user_interface' // TODO: implement const FLAG_PAYMENT_STORED_INTRUMENTS = 'payment_stored_instruments' // TODO: implement /** SHIPPING FLAGS (Shipping Provider) **/ -const FLAG_SHIPPING_STATUS = 'shipping_status' -const FLAG_SHIPPING_LABEL = 'shipping_label' // TODO: implement +const FLAG_SHIPPING_STATUS = 'shipping_status' // PROFESSIONAL +const FLAG_SHIPPING_LABEL = 'shipping_label' // ENTERPRISE TODO: implement /** SEARCH FLAGS (Search or Commerce Provider?) **/ -const FLAG_SEARCH_CUSTOMERS = 'search_customers' -const FLAG_SEARCH_PRODUCTS = 'search_products' // TODO: implement +const FLAG_SEARCH_CUSTOMERS = 'search_customers' // STARTER +const FLAG_SEARCH_PRODUCTS = 'search_products' // ENTERPRISE TODO: implement /** TAX FLAGS (Tax Provider?) **/ -const FLAG_TAX_CALCULATOR = 'tax_calculator' // TODO: implement +const FLAG_TAX_CALCULATOR = 'tax_calculator' // ENTERPRISE TODO: implement module.exports = [ ROLE_ADMIN, ROLE_AGENT, - FLAG_ORDER_HISTORY, + FLAG_ORDERS_LIST, FLAG_ORDER_DETAILS, FLAG_ORDER_FILTER, FLAG_ORDER_PIN, FLAG_ORDER_SORT, + FLAG_ORDER_TIMELINE, FLAG_ORDER_PAYMENT, FLAG_ORDER_REFUND, FLAG_ORDER_CREATE, diff --git a/src/index.js b/src/index.js index 21b0b110..503e6344 100644 --- a/src/index.js +++ b/src/index.js @@ -3,7 +3,7 @@ const { decryptAES, encryptAES, cleanProviders, - getFeatureFlags, + getSavedData, isNewThisPeriod, saveProviderData, createUsageRecords @@ -23,15 +23,20 @@ const { const { URL } = require('whatwg-url') const cors = require('micro-cors')() -const _toJSON = error => { - return !error +const _toJSON = errorObj => { + const formattedError = !errorObj ? '' - : Object.getOwnPropertyNames(error).reduce( + : typeof errorObj === 'string' + ? errorObj + : Object.getOwnPropertyNames(errorObj).reduce( (jsonError, key) => { - return { ...jsonError, [key]: error[key] } + return { ...jsonError, [key]: errorObj[key] } }, { type: 'error' } ) + return { + error: formattedError + } } process.on('unhandledRejection', (reason, p) => { @@ -44,19 +49,31 @@ process.on('unhandledRejection', (reason, p) => { }) const notAuthorized = async (req, res) => - send(res, 401, { - error: 'Referer or Origin not whitelisted' - }) + send( + res, + 401, + _toJSON({ + type: 'notAuthorized', + message: 'Referer or Origin not whitelisted' + }) + ) const notSupported = async (req, res) => - send(res, 405, { error: 'Method not supported yet' }) + send( + res, + 405, + _toJSON({ type: 'notSupported', message: 'Method not supported yet' }) + ) const notEncrypted = async (req, res) => - send(res, 412, { error: 'Payload must contain encrypted body' }) -const success = async (req, res, payload) => send(res, 200, payload) -const mocked = async (req, res) => - success(req, res, { - newThisPeriod: false, - featureFlags: flags - }) + send( + res, + 412, + _toJSON({ + type: 'notEncrypted', + message: 'Payload must contain encrypted body' + }) + ) +const success = async (req, res, encryptedPayload) => + send(res, 200, encryptedPayload) const prepareRegex = string => { return string @@ -116,22 +133,13 @@ const handleAuthorize = (req, res) => { } } -const handleError = (req, res, error) => { - console.warn('handleError.error', error) - // const jsonError = _toJSON(error) - // return send(res, error.statusCode || 500, jsonError) - //TODO!!!!!!!!!!!!!!!!!!!!!! - //TEMP!!!!!!!!!!!!!!!!!!!!!: swallow error - return mocked(req, res) -} - const getBody = async (req, res) => { let rawBody = {} try { rawBody = await json(req) // console.log('rawBody',rawBody) } catch (error) { - console.error(error) + console.warn('getBody, error', error) } if (!rawBody.encrypted) { @@ -144,6 +152,7 @@ const getBody = async (req, res) => { const body = safeParse( decryptAES(rawBody.encrypted, sharedSecret, initialVector) ) + console.log('body', body) return { body, initialVector } } @@ -164,41 +173,49 @@ const processPost = async (req, res) => { } const { body, initialVector } = decrypted - // console.log('processPost, body',body) + console.log('processPost, body', body) const { applicationId, collectionId, subscription, tracked } = body // collectionId = org, tracked = agent - // console.log('processPost, applicationId',applicationId) - // console.log('processPost, collectionId',collectionId) - // console.log('processPost, subscription',subscription) - // console.log('processPost, tracked',tracked) + console.log('processPost, applicationId', applicationId) + console.log('processPost, collectionId', collectionId) + console.log('processPost, subscription', subscription) + console.log('processPost, tracked', tracked) const { items: subscriptionItems } = subscription - // console.log('processPost, subscriptionItems',subscriptionItems) + console.log('processPost, subscriptionItems', subscriptionItems) if ( + !initialVector || !applicationId || !collectionId || !subscription || !tracked || !subscriptionItems ) { - return send(res, 400, { - applicationId, - collectionId, - subscription, - tracked, - subscriptionItems - }) + return send( + res, + 400, + _toJSON({ + type: 'requiredFields', + method: 'processPost', + fields: { + applicationId, + collectionId, + subscription, + tracked, + subscriptionItems + } + }) + ) } const responses = await Promise.all([ await isNewThisPeriod(applicationId, collectionId, subscription, tracked), - await getFeatureFlags(applicationId, collectionId, subscription) - ]).catch(error => handleError(req, res, error)) - // console.log('processPost, responses',responses) + await getSavedData(applicationId, collectionId, subscription) + ]) const [newThisPeriod, { featureFlags, providers }] = responses - // console.log('processPost, newThisPeriod',newThisPeriod) - // console.log('processPost, featureFlags',providers) - // console.log('processPost, providers',providers) + console.log('processPost, newThisPeriod', newThisPeriod) + console.log('processPost, featureFlags', providers) + console.log('processPost, providers', providers) const unencrypted = { newThisPeriod, featureFlags, @@ -206,23 +223,20 @@ const processPost = async (req, res) => { } // console.log('processPost, unencrypted',unencrypted) - const payload = { + const encryptedPayload = { encrypted: encryptAES(unencrypted, sharedSecret, initialVector) } // console.log('processPost, payload',payload) if (newThisPeriod) { - await createUsageRecords(subscriptionItems).catch(error => - handleError(req, res, error) - ) - return success(req, res, payload) + await createUsageRecords(subscriptionItems) + return success(req, res, encryptedPayload) } else { - return success(req, res, payload) + return success(req, res, encryptedPayload) } } catch (error) { - console.error('Error', error) - const jsonError = _toJSON(error) - return send(res, 500, jsonError) + console.error('processPost, error', error) + return send(res, 500, _toJSON(error)) } } @@ -243,15 +257,34 @@ const processPut = async (req, res) => { // console.log('processPut, providers', providers) // console.log('processPut, audit', audit) - if (!applicationId || !collectionId || !providers || !audit) { - return send(res, 400, { applicationId, collectionId, providers, audit }) + if ( + !initialVector || + !applicationId || + !collectionId || + !providers || + !audit + ) { + return send( + res, + 400, + _toJSON({ + type: 'requiredFields', + method: 'processPut', + fields: { + applicationId, + collectionId, + providers, + audit + } + }) + ) } await saveProviderData(applicationId, collectionId, providers, audit).catch( error => handleError(req, res, error) ) - const payload = { + const encryptedPayload = { encrypted: encryptAES( { providers @@ -261,19 +294,18 @@ const processPut = async (req, res) => { ) } - return success(req, res, payload) + return success(req, res, encryptedPayload) } catch (error) { - console.error('Error', error) - const jsonError = _toJSON(error) - return send(res, 500, jsonError) + console.error('processPut, error', error) + return send(res, 500, _toJSON(error)) } } module.exports = cors( router( options('/*', processOptions), - post('/*', processPost), - put('/*', processPut), + post('/*', processPost), // track + put('/*', processPut), // save get('/*', notSupported), patch('/*', notSupported), del('/*', notSupported), diff --git a/src/utils.js b/src/utils.js index 64ee9680..a55ef4d5 100644 --- a/src/utils.js +++ b/src/utils.js @@ -229,7 +229,7 @@ module.exports = { }) }, - getFeatureFlags(applicationId, collectionId, subscription) { + getSavedData(applicationId, collectionId, subscription) { // collectionId = org return new Promise((resolve, reject) => { const { @@ -240,9 +240,17 @@ module.exports = { .doc(`${applicationId}`) .collection(`${collectionId}`) + console.log('applicationId', applicationId) + console.log('collectionId', collectionId) + return appConfigCollection .get() .then(providerDocs => { + console.log('providerDocs', providerDocs) + console.log('providerDocs.size', providerDocs.size) + console.log('providerDocs.docs', providerDocs.docs) + console.log('providerDocs.docs.length', providerDocs.docs.length) + let providers = {} providerDocs.forEach(providerDoc => { const providerType = providerDoc.id @@ -270,7 +278,7 @@ module.exports = { return providers }) .then(providers => { - // console.log(`providers: ${JSON.stringify(providers)}`) + console.log(`providers: ${JSON.stringify(providers)}`) const subscriptionRef = firestore .collection('feature-flags') @@ -285,12 +293,13 @@ module.exports = { return filterEnabledFlags(subscriptionFlags) }) .then(enabledSubsciptionFlags => { - // console.log('enabledSubsciptionFlags', enabledSubsciptionFlags) + // console.log(`enabledSubsciptionFlags[${planId}]`, enabledSubsciptionFlags) const providerRefs = Object.entries(providers).map( ([ providerType, { type: providerName, version: providerVersion } ]) => { + // console.log(`feature-flags>${applicationId}>${providerType}>${providerName}>${providerVersion}`) return firestore .collection('feature-flags') .doc(`${applicationId}`) @@ -300,24 +309,32 @@ module.exports = { .doc(`${providerVersion}`) } ) - return firestore - .getAll(...providerRefs) - .then(providerFlags => { - return filterEnabledFlags(providerFlags) - }) - .then(enabledProviderFlags => { - // console.log('enabledProviderFlags',enabledProviderFlags) - return enabledSubsciptionFlags.filter(enabledSubsciberFlag => - enabledProviderFlags.includes(enabledSubsciberFlag) - ) - }) + // console.log('providerRefs',providerRefs) + // console.log('providerRefs.length',providerRefs.length) + + // this would happen if no providers have been saved for the collectionId + return !providerRefs || !providerRefs.length + ? [] + : // ? enabledSubsciptionFlags + firestore + .getAll(...providerRefs) + .then(providerFlags => { + return filterEnabledFlags(providerFlags) + }) + .then(enabledProviderFlags => { + console.log('enabledProviderFlags', enabledProviderFlags) + return enabledSubsciptionFlags.filter( + enabledSubsciberFlag => + enabledProviderFlags.includes(enabledSubsciberFlag) + ) + }) }) .then(enabledSubscriptionProviderFlags => { // console.log('enabledSubscriptionProviderFlags',enabledSubscriptionProviderFlags) const accountRef = firestore .collection('feature-flags') .doc(`${applicationId}`) - .collection(`account`) + .collection(`installation`) .doc(`${collectionId}`) return firestore @@ -334,7 +351,8 @@ module.exports = { return [...new Set(enabledAccountSubscriptionProviderFlags)] // removes dupes }) .then(featureFlags => { - // console.log('featureFlags', featureFlags) + console.log('featureFlags', featureFlags) + console.log('providers', providers) resolve({ featureFlags, providers }) }) })