Skip to content
This repository has been archived by the owner on May 28, 2023. It is now read-only.

Commit

Permalink
Merge pull request #217 from DivanteLtd/develop
Browse files Browse the repository at this point in the history
1.9-rc2 release
  • Loading branch information
lukeromanowicz authored Apr 17, 2019
2 parents 0097798 + 5d0ad49 commit d3fb13c
Show file tree
Hide file tree
Showing 18 changed files with 1,181 additions and 981 deletions.
22 changes: 22 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
sudo: required
language: node_js

cache:
yarn: true
directories:
- node_modules

install:
- yarn

jobs:
include:
- stage: Build
script:
- yarn lint
- yarn build
node_js: "8"
- script:
- yarn lint
- yarn build
node_js: "10"
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,24 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.9.0-rc.2] - unreleased
- Update Babel from 6 to 7 - @lukeromanowicz
- Support unicode characters in order requests - @lukeromanowicz (#201)
- TravisCI configured for building and linting - @lukeromanowicz (#204)
- Use Redis database from configuration in mage2vs - @Cyclonecode (#211)

## [1.9.0-rc.1] - 2019.03.04
- Changed location of magento1 platform js client. Moved from `src/platform/magento1/module` to [magento1-vsbridge-client](https://github.com/DivanteLtd/magento1-vsbridge-client) - @mtarld (#195)

## [1.8.4] - 2019.04.17
- Use encrypted token for user authentication - @pkarw

## [1.8.3] - 2019.03.05
- Use store id from configuration in `mage2vs import` - @boehsermoe (#179)

## [1.8.2] - 2019.03.04
- Magento 1 bridge client - @afirlejczyk (#190)
- configurable ElasticSearch `apiVersion` - @Resubaka (#192)

## [1.8.1] - 2019.02.11
- Fixed `apiVersion` property for ElasticSearch driver - now it's available thru `config/*.json` - @mdanilowicz (#185)
11 changes: 11 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
presets: [
[
'@babel/preset-env', {
targets: {
node: "8"
}
}
]
]
};
1 change: 1 addition & 0 deletions docker-compose.nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ services:
- './ecosystem.json:/var/www/ecosystem.json'
- './migrations:/var/www/migrations'
- './package.json:/var/www/package.json'
- './babel.config.js:/var/www/babel.config.js'
- './scripts:/var/www/scripts'
- './src:/var/www/src'
- './var:/var/www/var'
Expand Down
12 changes: 6 additions & 6 deletions migrations/1530101328854-local_es_config_fix.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ var files = fs.readdirSync(configDir).filter(function(file) {

module.exports.up = next => {
files.forEach(function(file) {
var file = path.join(configDir, file)
var path = path.join(configDir, file)

try {
console.log(`Searching for deprecated parameters in file '${file}'...`)
let config = JSON.parse(fs.readFileSync(file))
console.log(`Searching for deprecated parameters in file '${path}'...`)
let config = JSON.parse(fs.readFileSync(path))

if ("esHost" in config) {
console.log("Parameter 'esHost' found - rewriting...", file)
console.log("Parameter 'esHost' found - rewriting...", path)
let esHostPort = config.esHost.split(':')
_set(config, 'elasticsearch.host', esHostPort[0])
_set(config, 'elasticsearch.port', esHostPort[1])
Expand All @@ -37,8 +37,8 @@ module.exports.up = next => {
delete config.esIndexes
}

fs.writeFileSync(file, JSON.stringify(config, null, 2))
console.log(`File '${file}' updated.`)
fs.writeFileSync(path, JSON.stringify(config, null, 2))
console.log(`File '${path}' updated.`)
} catch (e) {
throw e
}
Expand Down
19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"description": "vue-storefront API and data services",
"main": "dist",
"scripts": {
"dev": "nodemon -w src --exec \"babel-node src --presets env,stage-0\"",
"build": "babel src -s -D -d dist --presets env,stage-0",
"dev": "nodemon -w src --exec \"babel-node src\"",
"build": "babel src -s -D -d dist",
"start": "pm2 start ecosystem.json $PM2_ARGS",
"db": "node scripts/db.js",
"seo": "node scripts/seo.js",
Expand All @@ -33,11 +33,12 @@
"eslintConfig": {
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 7,
"ecmaVersion": 8,
"sourceType": "module"
},
"env": {
"node": true
"node": true,
"es6": true
},
"rules": {
"no-console": 0,
Expand All @@ -52,6 +53,7 @@
"license": "MIT",
"dependencies": {
"ajv": "^6.4.0",
"ajv-keywords": "^3.4.0",
"body-parser": "^1.18.2",
"bodybuilder": "2.2.13",
"commander": "^2.19.0",
Expand Down Expand Up @@ -88,12 +90,11 @@
"winston": "^2.4.2"
},
"devDependencies": {
"@babel/polyfill": "^7.2.5",
"apollo-server-express": "^1.3.6",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-0": "^6.24.1",
"@babel/cli": "^7.2.3",
"@babel/core": "^7.4.0",
"@babel/node": "^7.2.2",
"@babel/preset-env": "^7.4.2",
"eslint": "^4.16.0",
"nodemon": "^1.18.7"
},
Expand Down
1 change: 1 addition & 0 deletions scripts/mage2vs.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function getMagentoDefaultConfig(storeCode) {
MAGENTO_URL: apiConfig.url,
REDIS_HOST: config.redis.host,
REDIS_PORT: config.redis.port,
REDIS_DB: config.redis.db,
INDEX_NAME: config.elasticsearch.indices[0],
DATABASE_URL: `${config.elasticsearch.protocol}://${config.elasticsearch.host}:${config.elasticsearch.port}`
}
Expand Down
6 changes: 3 additions & 3 deletions src/api/order.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ export default ({ config, db }) => resource({
* POST create an order with JSON payload compliant with models/order.md
*/
create(req, res) {


const ajv = new Ajv();
require('ajv-keywords')(ajv, 'regexp');

const orderSchema = require('../models/order.schema.json')
const orderSchemaExtension = require('../models/order.schema.extension.json')
const validate = ajv.compile(merge(orderSchema, orderSchemaExtension));
Expand All @@ -35,7 +35,7 @@ export default ({ config, db }) => resource({
console.dir(validate.errors);
apiStatus(res, validate.errors, 500);
return;
}
}
const incomingOrder = { title: 'Incoming order received on ' + new Date() + ' / ' + req.ip, ip: req.ip, agent: req.headers['user-agent'], receivedAt: new Date(), order: req.body }/* parsed using bodyParser.json middleware */
console.log(JSON.stringify(incomingOrder))

Expand Down
27 changes: 16 additions & 11 deletions src/api/user.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { apiStatus } from '../lib/util';
import { apiStatus, encryptToken, decryptToken } from '../lib/util';
import { Router } from 'express';
import PlatformFactory from '../platform/factory';
import jwt from 'jwt-simple';
Expand Down Expand Up @@ -68,12 +68,12 @@ export default ({config, db}) => {
*/
if (config.usePriceTiers) {
userProxy.me(result).then((resultMe) => {
apiStatus(res, result, 200, {refreshToken: jwt.encode(req.body, config.authHashSecret ? config.authHashSecret : config.objHashSecret)});
apiStatus(res, result, 200, {refreshToken: encryptToken(jwt.encode(req.body, config.authHashSecret ? config.authHashSecret : config.objHashSecret), config.authHashSecret ? config.authHashSecret : config.objHashSecret)});
}).catch(err => {
apiStatus(res, err, 500);
})
} else {
apiStatus(res, result, 200, {refreshToken: jwt.encode(req.body, config.authHashSecret ? config.authHashSecret : config.objHashSecret)});
apiStatus(res, result, 200, {refreshToken: encryptToken(jwt.encode(req.body, config.authHashSecret ? config.authHashSecret : config.objHashSecret), config.authHashSecret ? config.authHashSecret : config.objHashSecret)});
}
}).catch(err => {
apiStatus(res, err, 500);
Expand All @@ -89,16 +89,21 @@ export default ({config, db}) => {
if (!req.body || !req.body.refreshToken) {
return apiStatus(res, 'No refresh token provided', 500);
}
try {
const decodedToken = jwt.decode(req.body ? decryptToken(req.body.refreshToken, config.authHashSecret ? config.authHashSecret : config.objHashSecret) : '', config.authHashSecret ? config.authHashSecret : config.objHashSecret)

const decodedToken = jwt.decode(req.body ? req.body.refreshToken : '', config.authHashSecret ? config.authHashSecret : config.objHashSecret)
if (!decodedToken) {
return apiStatus(res, 'Invalid refresh token provided', 500);
if (!decodedToken) {
return apiStatus(res, 'Invalid refresh token provided', 500);
}

userProxy.login(decodedToken).then((result) => {
apiStatus(res, result, 200, {refreshToken: encryptToken(jwt.encode(decodedToken, config.authHashSecret ? config.authHashSecret : config.objHashSecret), config.authHashSecret ? config.authHashSecret : config.objHashSecret)});
}).catch(err => {
apiStatus(res, err, 500);
})
} catch (err) {
return apiStatus(res, err.message, 500);
}
userProxy.login(decodedToken).then((result) => {
apiStatus(res, result, 200, {refreshToken: jwt.encode(decodedToken, config.authHashSecret ? config.authHashSecret : config.objHashSecret)});
}).catch(err => {
apiStatus(res, err, 500);
})
});

/**
Expand Down
1 change: 0 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import '@babel/polyfill/noConflict';
import http from 'http';
import express from 'express';
import cors from 'cors';
Expand Down
17 changes: 17 additions & 0 deletions src/lib/util.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import config from 'config';
import crypto from 'crypto';
const algorithm = 'aes-256-ctr';

/** Creates a callback that proxies node callback style arguments to an Express Response object.
* @param {express.Response} res Express HTTP Response
* @param {number} [status=200] Status code to send on success
Expand Down Expand Up @@ -42,3 +45,17 @@ export function apiStatus(res, result = 'OK', code = 200, meta = null) {
res.status(code).json(apiResult);
return result;
}

export function encryptToken(textToken, secret) {
const cipher = crypto.createCipher(algorithm, secret)
let crypted = cipher.update(textToken, 'utf8', 'hex')
crypted += cipher.final('hex');
return crypted;
}

export function decryptToken(textToken, secret) {
const decipher = crypto.createDecipher(algorithm, secret)
let dec = decipher.update(textToken, 'hex', 'utf8')
dec += decipher.final('utf8');
return dec;
}
40 changes: 28 additions & 12 deletions src/models/order.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
{
"required": [ "sku", "price", "qty" ],
"properties": {
"sku": { "type": "string", "minLength": 1, "pattern": "[a-zA-Z0-9_]+" },
"sku": { "type": "string", "minLength": 1, "regexp": "/[\\p{L}\\d_]+/u" },
"qty": { "type" : "number", "minimum": 1 },
"name": { "type": "string", "minLength": 1, "pattern": "[a-zA-Z0-9_]+" },
"name": { "type": "string", "minLength": 1, "regexp": "/[\\p{L}\\d_]+/u" },
"price": { "type" : "number", "minimum": 1 },
"product_type": { "type": "string", "minLength": 1, "pattern": "[a-zA-Z]+" }
"product_type": { "type": "string", "minLength": 1, "regexp": "/[\\p{L}]+/u" }
}
}
]
Expand All @@ -46,10 +46,18 @@
},
"company": { "type": "string" },
"telephone": { "type": "string" },
"postcode": { "type": "string", "minLength": 3, "pattern": "[a-zA-Z0-9_]+" },
"city": { "type": "string", "pattern": "[a-zA-Z]+" },
"firstname": { "type": "string", "pattern": "[a-zA-Z]+", "description": "First name" },
"lastname": { "type": "string", "pattern": "[a-zA-Z]+" },
"postcode": { "type": "string", "minLength": 3, "regexp": "/[\\p{L}\\d_]+/u"},
"city": { "type": "string", "regexp": "/[\\p{L}]+/u" },
"firstname": {
"type": "string",
"regexp": "/[\\p{L}]+/u",
"description": "First name"
},
"lastname": {
"type": "string",
"regexp": "/[\\p{L}]+/u",
"description": "Last name"
},
"email": { "type": "string", "pattern": "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?" },
"region_code":{ "type": "string" },
"sameAsBilling": { "type": "number"}
Expand All @@ -68,10 +76,18 @@
},
"company": { "type": "string" },
"telephone": { "type": "string" },
"postcode": { "type": "string", "minLength": 3, "pattern": "[a-zA-Z0-9_]+" },
"city": { "type": "string", "pattern": "[a-zA-Z]+" },
"firstname": { "type": "string", "pattern": "[a-zA-Z]+" },
"lastname": { "type": "string", "pattern": "[a-zA-Z]+" },
"postcode": { "type": "string", "minLength": 3, "regexp": "/[\\p{L}\\d_]+/u"},
"city": { "type": "string", "regexp": "/[\\p{L}]+/u" },
"firstname": {
"type": "string",
"regexp": "/[\\p{L}]+/u",
"description": "First name"
},
"lastname": {
"type": "string",
"regexp": "/[\\p{L}]+/u",
"description": "Last name"
},
"email": { "type": "string", "pattern": "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?" },
"region_code":{ "type": "string" },
"sameAsBilling": { "type": "number"}
Expand All @@ -85,4 +101,4 @@
}
}
}
}
}
16 changes: 16 additions & 0 deletions src/platform/magento1/order.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import AbstractOrderProxy from '../abstract/order'
import { multiStoreConfig } from './util'

class OrderProxy extends AbstractOrderProxy {
constructor (config, req) {
const Magento1Client = require('magento1-vsbridge-client').Magento1Client;
super(config, req)
this.api = Magento1Client(multiStoreConfig(config.magento1.api, req));
}

create (orderData) {
return this.api.order.create(orderData);
}
}

module.exports = OrderProxy
7 changes: 4 additions & 3 deletions src/platform/magento1/tax.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class TaxProxy extends AbstractTaxProxy {

if (this._config.storeViews && this._config.storeViews.multistore) {
for (let storeCode in this._config.storeViews){
let store = this._config.storeViews[storeCode]
const store = this._config.storeViews[storeCode]

if (typeof store === 'object') {
if (store.elasticsearch && store.elasticsearch.index) { // workaround to map stores
if (store.elasticsearch.index === indexName) {
Expand Down Expand Up @@ -56,7 +57,7 @@ class TaxProxy extends AbstractTaxProxy {
}

process (productList, groupId = null) {
let inst = this
const inst = this
return new Promise ((resolve, reject) => {
inst.applyTierPrices(productList, groupId)

Expand All @@ -74,7 +75,7 @@ class TaxProxy extends AbstractTaxProxy {
esConfig.httpAuth = this._config.elasticsearch.user + ':' + this._config.elasticsearch.password
}

let client = new es.Client(esConfig)
const client = new es.Client(esConfig)
const esQuery = {
index: this._indexName,
type: 'taxrule',
Expand Down
1 change: 1 addition & 0 deletions src/platform/magento1/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ export function multiStoreConfig(apiConfig, req) {
console.error('Unavailable store code', storeCode)
}
}

return confCopy
}
Loading

0 comments on commit d3fb13c

Please sign in to comment.