ti2 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ const assert = require('assert');
2
+ const faker = require('faker');
3
+
4
+ module.exports = {
5
+ up: async queryInterface => {
6
+ const payload = {
7
+ name: 'tourconnect',
8
+ packageName: 'ti2-tourconnect',
9
+ adminEmail: 'ti2@tourconnect.com',
10
+ createdAt: new Date(),
11
+ updatedAt: new Date(),
12
+ };
13
+ await queryInterface.bulkInsert('Integrations', [payload]);
14
+ },
15
+ down: async queryInterface => {
16
+ await queryInterface.bulkDelete('Integrations', [{
17
+ name: 'tourconnect',
18
+ }]);
19
+ },
20
+ };
@@ -0,0 +1,14 @@
1
+
2
+ module.exports = {
3
+ up: (queryInterface, Sequelize) => queryInterface.addColumn(
4
+ 'Integrations',
5
+ 'deletedAt',
6
+ {
7
+ type: Sequelize.DATE,
8
+ allowNull: true,
9
+ validate: {
10
+ },
11
+ },
12
+ ),
13
+ down: queryInterface => queryInterface.removeColumn('Integrations', 'deletedAt'),
14
+ };
@@ -0,0 +1,10 @@
1
+ module.exports = {
2
+ up: (queryInterface, Sequelize) => queryInterface.changeColumn('UserAppKeys', 'appKey', {
3
+ type: Sequelize.TEXT,
4
+ allowNull: false,
5
+ }),
6
+ down: (queryInterface, Sequelize) => queryInterface.changeColumn('UserAppKeys', 'appKey', {
7
+ type: Sequelize.STRING,
8
+ allowNull: false,
9
+ })
10
+ };
package/models/db.js ADDED
@@ -0,0 +1,16 @@
1
+ const Sequelize = require('sequelize');
2
+
3
+ const {
4
+ env: {
5
+ DB_URL,
6
+ },
7
+ } = process;
8
+
9
+ const options = {
10
+ operatorsAliases: false,
11
+ logging: false,
12
+ };
13
+
14
+ const sequelize = new Sequelize(DB_URL, options);
15
+
16
+ module.exports = sequelize;
@@ -0,0 +1,27 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const Sequelize = require('sequelize');
4
+ const sequelize = require('./db');
5
+
6
+ const basename = path.basename(__filename);
7
+ const models = {};
8
+
9
+ fs
10
+ .readdirSync(__dirname)
11
+ .filter(file => (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'))
12
+ .forEach(file => {
13
+ const model = require(path.join(__dirname, file));
14
+ models[model.name] = model;
15
+ });
16
+
17
+ Object.keys(models).forEach(modelName => {
18
+ if (models[modelName].associate) {
19
+ models[modelName].associate(models);
20
+ }
21
+ });
22
+
23
+ module.exports = {
24
+ ...models,
25
+ sequelize,
26
+ Sequelize,
27
+ };
@@ -0,0 +1,71 @@
1
+ const crypto = require('crypto');
2
+ const Sequelize = require('sequelize');
3
+ const db = require('./db');
4
+
5
+ const { env: { dbCryptoKey } } = process;
6
+ const generateKey = () => {
7
+ const newKey = `${crypto.randomBytes(5).toString('base64').replace(/\W/g, '')}.${crypto.randomBytes(32).toString('base64').replace(/\W/g, '')}`;
8
+ return newKey;
9
+ };
10
+
11
+ const encrypt = text => {
12
+ const iv = crypto.randomBytes(16);
13
+ const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(dbCryptoKey, 'base64'), iv);
14
+ let encrypted = cipher.update(text);
15
+ encrypted = Buffer.concat([encrypted, cipher.final()]);
16
+ return `${iv.toString('hex')}%${encrypted.toString('hex')}`;
17
+ };
18
+
19
+ const decrypt = text => {
20
+ const iv = Buffer.from(text.split('%')[0], 'hex');
21
+ const encryptedText = Buffer.from(text.split('%')[1], 'hex');
22
+ const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(dbCryptoKey, 'base64'), iv);
23
+ let decrypted = decipher.update(encryptedText);
24
+ decrypted = Buffer.concat([decrypted, decipher.final()]);
25
+ return decrypted.toString();
26
+ };
27
+
28
+ const Integration = db.define('Integration', {
29
+ name: {
30
+ type: Sequelize.STRING,
31
+ primaryKey: true,
32
+ allowNull: false,
33
+ validate: {
34
+ is: /^((?!true|false|TRUE|FALSE).){1,255}$/,
35
+ },
36
+ },
37
+ packageName: Sequelize.STRING,
38
+ adminEmail: Sequelize.STRING,
39
+ apiKey: {
40
+ type: Sequelize.STRING,
41
+ defaultValue: () => {
42
+ const newKey = generateKey();
43
+ return encrypt(newKey);
44
+ },
45
+ },
46
+ lastSeen: Sequelize.INTEGER,
47
+ }, {
48
+ paranoid: true,
49
+ getterMethods: {
50
+ apiKey() {
51
+ if (!this.getDataValue('apiKey')) { // there is no secret, probably is a combined request
52
+ return generateKey();
53
+ }
54
+ return decrypt(this.getDataValue('apiKey'));
55
+ },
56
+ },
57
+ setterMethods: {
58
+ apiKey(value) {
59
+ return encrypt(value);
60
+ },
61
+ },
62
+ });
63
+
64
+ Integration.associate = models => {
65
+ Integration.hasMany(models.UserAppKey, {
66
+ foreignKey: 'integrationId',
67
+ });
68
+ };
69
+ Integration.generateKey = generateKey;
70
+
71
+ module.exports = Integration;
package/models/user.js ADDED
@@ -0,0 +1,17 @@
1
+ const Sequelize = require('sequelize');
2
+ const db = require('./db');
3
+
4
+ const User = db.define('User', {
5
+ userId: {
6
+ type: Sequelize.STRING,
7
+ primaryKey: true,
8
+ },
9
+ }, {});
10
+ User.associate = models => {
11
+ User.hasMany(models.UserAppKey, {
12
+ foreignKey: 'userId',
13
+ });
14
+ // associations can be defined here
15
+ };
16
+
17
+ module.exports = User;
@@ -0,0 +1,59 @@
1
+ const jwt = require('jsonwebtoken');
2
+ const Sequelize = require('sequelize');
3
+ const { omit } = require('ramda');
4
+ const db = require('./db');
5
+
6
+ const { env: { dbCryptoKey } } = process;
7
+
8
+ const UserAppKey = db.define('UserAppKey', {
9
+ id: {
10
+ allowNull: false,
11
+ type: Sequelize.INTEGER(10),
12
+ primaryKey: true,
13
+ autoIncrement: true,
14
+ },
15
+ userId: {
16
+ type: Sequelize.STRING,
17
+ allowNull: false,
18
+ validate: {
19
+ is: /^((?!true|false|TRUE|FALSE).){1,255}$/,
20
+ },
21
+ },
22
+ integrationId: {
23
+ type: Sequelize.STRING,
24
+ allowNull: false,
25
+ validate: {
26
+ is: /^((?!true|false|TRUE|FALSE).){1,255}$/,
27
+ },
28
+ },
29
+ hint: {
30
+ type: Sequelize.STRING,
31
+ allowNull: false,
32
+ validate: {
33
+ is: /^((?!true|false|TRUE|FALSE).){1,255}$/,
34
+ },
35
+ },
36
+ appKey: {
37
+ type: Sequelize.TEXT,
38
+ allowNull: false,
39
+ set: function setter(value, field) {
40
+ const newValue = jwt.sign(value, dbCryptoKey);
41
+ this.setDataValue(field, newValue);
42
+ },
43
+ get: function getter(field) {
44
+ const retValue = jwt.verify(this.getDataValue(field), dbCryptoKey);
45
+ return omit(['iat'], retValue);
46
+ },
47
+ },
48
+ }, {});
49
+ UserAppKey.associate = models => {
50
+ UserAppKey.belongsTo(models.User, {
51
+ foreignKey: 'userId',
52
+ as: 'user',
53
+ });
54
+ UserAppKey.belongsTo(models.Integration, {
55
+ foreignKey: 'integrationId',
56
+ as: 'integration',
57
+ });
58
+ };
59
+ module.exports = UserAppKey;
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "ti2",
3
+ "version": "1.0.0",
4
+ "description": "Tourist Industry Exchange (TI2)",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "jest",
8
+ "sequelize": "sequelize-cli"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/TourConnect/ti2.git"
13
+ },
14
+ "author": "",
15
+ "license": "GPL-3",
16
+ "bugs": {
17
+ "url": "https://github.com/TourConnect/ti2/issues"
18
+ },
19
+ "homepage": "https://github.com/TourConnect/ti2#readme",
20
+ "dependencies": {
21
+ "bluebird": "^3.7.2",
22
+ "express": "^4.17.2",
23
+ "js-yaml": "^4.1.0",
24
+ "jsonwebtoken": "^8.5.1",
25
+ "jwt-promise": "^1.0.0",
26
+ "mysql2": "^2.3.3",
27
+ "ramda": "^0.28.0",
28
+ "seque": "^1.2.1",
29
+ "sequelize": "^6.13.0",
30
+ "swagger-express-middleware": "^3.0.0-alpha.5",
31
+ "swagger-routes-express": "^3.3.1",
32
+ "swagger-ui-express": "^4.3.0",
33
+ "uninstall": "^0.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "eslint": "^8.7.0",
37
+ "eslint-config-airbnb-base": "^15.0.0",
38
+ "eslint-plugin-import": "^2.25.4",
39
+ "sequelize-cli": "^6.4.1"
40
+ }
41
+ }