exodus-framework 2.0.756 → 2.0.758

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.
Files changed (59) hide show
  1. package/lib/app/app.js +84 -0
  2. package/lib/app/controller.js +95 -0
  3. package/lib/app/core.js +71 -0
  4. package/lib/app/error.js +66 -0
  5. package/lib/app/index.js +72 -0
  6. package/lib/app/service.js +24 -0
  7. package/lib/app/settings.js +138 -0
  8. package/lib/app/singleton.js +29 -0
  9. package/lib/contracts/console.js +5 -0
  10. package/lib/contracts/entity.js +5 -0
  11. package/lib/contracts/http.js +50 -0
  12. package/lib/contracts/index.js +104 -0
  13. package/lib/contracts/messaging.js +25 -0
  14. package/lib/contracts/security.js +5 -0
  15. package/lib/contracts/service.js +5 -0
  16. package/lib/contracts/session.js +5 -0
  17. package/lib/contracts/settings.js +5 -0
  18. package/lib/contracts/singleton.js +5 -0
  19. package/lib/contracts/socket.js +11 -0
  20. package/lib/controllers/api/file.js +24 -0
  21. package/lib/controllers/api/index.js +13 -0
  22. package/lib/controllers/index.js +16 -0
  23. package/lib/controllers/messaging/application.js +63 -0
  24. package/lib/controllers/messaging/database.js +63 -0
  25. package/lib/controllers/messaging/environment.js +100 -0
  26. package/lib/express.d.js +5 -0
  27. package/lib/index.d.ts +0 -1
  28. package/lib/index.d.ts.map +1 -1
  29. package/lib/index.js +81 -0
  30. package/lib/middlewares/access.js +77 -0
  31. package/lib/middlewares/authentication.js +21 -0
  32. package/lib/middlewares/file.js +41 -0
  33. package/lib/middlewares/index.js +27 -0
  34. package/lib/models/Application.js +61 -0
  35. package/lib/models/DatabaseHost.js +62 -0
  36. package/lib/models/EnvConnection.js +41 -0
  37. package/lib/models/index.js +46 -0
  38. package/lib/routes/index.js +16 -0
  39. package/lib/routes/messaging/index.js +34 -0
  40. package/lib/services/express.d.ts +0 -1
  41. package/lib/services/express.d.ts.map +1 -1
  42. package/lib/services/express.js +152 -0
  43. package/lib/services/file.js +65 -0
  44. package/lib/services/index.d.ts +0 -1
  45. package/lib/services/index.d.ts.map +1 -1
  46. package/lib/services/index.js +76 -0
  47. package/lib/services/rabitmq.js +101 -0
  48. package/lib/services/redis.js +62 -0
  49. package/lib/services/security.js +229 -0
  50. package/lib/services/sequelize.js +285 -0
  51. package/lib/services/socket.js +55 -0
  52. package/lib/services/task.js +164 -0
  53. package/lib/utils/api.js +50 -0
  54. package/lib/utils/database.js +158 -0
  55. package/lib/utils/date.js +28 -0
  56. package/lib/utils/index.js +60 -0
  57. package/lib/utils/logger.js +51 -0
  58. package/lib/utils/session.js +23 -0
  59. package/package.json +1 -1
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _amqplib = _interopRequireDefault(require("amqplib"));
8
+ var _app = require("../app");
9
+ var _service = _interopRequireDefault(require("../app/service"));
10
+ var _messaging = _interopRequireDefault(require("../routes/messaging"));
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ /**
13
+ * Serviço de Mensageria
14
+ *
15
+ * @class RabbitMQService
16
+ * @extends {Service}
17
+ * @implements {IService}
18
+ */
19
+ class RabbitMQService extends _service.default {
20
+ connection;
21
+ channel;
22
+ connected;
23
+ mainRouter;
24
+
25
+ //# Initialization
26
+ constructor() {
27
+ super();
28
+ }
29
+ async init() {
30
+ if (!this.mainRouter) throw new Error('Need router'); //!sem router
31
+
32
+ this.mainRouter = {
33
+ ..._messaging.default,
34
+ ...this.mainRouter
35
+ }; // # Register native router
36
+ await this.connect();
37
+ }
38
+ async registerHandles() {
39
+ for (const topic of Object.keys(this.mainRouter)) {
40
+ await this.channel.bindQueue(_app.Core.settings.getAppication().appId, _app.Core.settings.getMessaging().exchanges.main, topic);
41
+ }
42
+ await this.channel.consume(_app.Core.settings.getAppication().appId, this.consumeFromQueue.bind(this), {
43
+ noAck: false
44
+ });
45
+ }
46
+ async connect() {
47
+ if (this.connected && this.channel) return;else this.connected = true;
48
+ try {
49
+ this.log(`⌛️ Connecting to Rabbit-MQ Server`);
50
+ this.connection = await _amqplib.default.connect(`amqp://${_app.Core.settings.getMessaging().user}:${_app.Core.settings.getMessaging().pass}@${_app.Core.settings.getMessaging().host}:5672`);
51
+ this.log(`✅ Rabbit MQ Connection is ready`);
52
+ this.channel = await this.connection.createChannel();
53
+ await this.channel.assertExchange(_app.Core.settings.getMessaging().exchanges.main, 'topic', {
54
+ durable: true
55
+ });
56
+ await this.channel.assertQueue(_app.Core.settings.getAppication().appId, {
57
+ durable: true
58
+ });
59
+ this.log(`🛸 Created RabbitMQ Channel successfully`);
60
+ this.registerHandles();
61
+ } catch (error) {
62
+ throw new _app.ErrorHandler(`Not connected to MQ Server`, error); // ! throw because starting process
63
+ }
64
+ }
65
+
66
+ //# Common
67
+ async sendToQueue(topic, data) {
68
+ try {
69
+ if (!this.channel) {
70
+ await this.connect();
71
+ }
72
+ this.channel.publish(_app.Core.settings.getMessaging().exchanges.main, topic, Buffer.from(JSON.stringify({
73
+ ...data,
74
+ serviceId: _app.Core.settings.getAppication().appId
75
+ })), {
76
+ messageId: new Date().toDateString(),
77
+ persistent: true
78
+ });
79
+ } catch (error) {
80
+ new _app.ErrorHandler('Houve um erro no envio de uma mensagem para o rabitmq', error);
81
+ }
82
+ }
83
+ async consumeFromQueue(msg) {
84
+ if (!msg) {
85
+ return this.log(`Invalid incoming message in`);
86
+ }
87
+ try {
88
+ const topic = msg.fields.routingKey;
89
+ const content = JSON.parse(msg.content.toString());
90
+ const callBack = this.mainRouter[topic];
91
+ callBack(content.data, () => this.channel.ack(msg), content.serviceId);
92
+ } catch (error) {
93
+ this.channel.ack(msg);
94
+ new _app.ErrorHandler('Error on parsing message from queue', error);
95
+ }
96
+ }
97
+ registerRouter(router) {
98
+ this.mainRouter = router;
99
+ }
100
+ }
101
+ var _default = exports.default = RabbitMQService;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _redis = require("redis");
8
+ var _app = require("../app");
9
+ var _service = _interopRequireDefault(require("../app/service"));
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ /**
12
+ * Serviço de cache
13
+ *
14
+ * @class RedisService
15
+ * @extends {Service}
16
+ * @implements {IService}
17
+ */
18
+ class RedisService extends _service.default {
19
+ client;
20
+
21
+ //* Initialization
22
+ async init() {
23
+ this.client = (0, _redis.createClient)({
24
+ url: `redis://${_app.Core.settings.getCache().host}:${_app.Core.settings.getCache().port}`,
25
+ password: _app.Core.settings.getCache().password
26
+ });
27
+ await this.connect();
28
+ }
29
+ connect() {
30
+ this.client.on('error', this.onClientError.bind(this));
31
+ return new Promise((resolve, reject) => {
32
+ this.client.connect().then(() => {
33
+ this.log('Redis client connected.', 'success');
34
+ resolve(true);
35
+ }).catch(reason => {
36
+ new _app.ErrorHandler('Error on conecting Redis', reason);
37
+ reject(reason);
38
+ });
39
+ });
40
+ }
41
+ async disconnect() {
42
+ await this.client.quit();
43
+ }
44
+
45
+ //* Common
46
+ async setValue(key, value) {
47
+ await this.client.set(key, value);
48
+ }
49
+ async getValue(key) {
50
+ const value = await this.client.get(key);
51
+ return value;
52
+ }
53
+ async deleteValue(key) {
54
+ await this.client.del(key);
55
+ }
56
+
57
+ //* Events
58
+ onClientError(err) {
59
+ new _app.ErrorHandler('Error on init redis client', err);
60
+ }
61
+ }
62
+ var _default = exports.default = RedisService;
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var crypto = _interopRequireWildcard(require("crypto"));
8
+ var fs = _interopRequireWildcard(require("fs"));
9
+ var _nodeJose = require("node-jose");
10
+ var _path = _interopRequireDefault(require("path"));
11
+ var _app = require("../app");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
14
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
15
+ class SecurityService extends _app.Service {
16
+ privateKey;
17
+ publicKey;
18
+ servicePublicKey;
19
+ async init() {
20
+ this.checkPaths();
21
+ await this.loadPrivateKey();
22
+ await this.loadPublicKey();
23
+ await this.loadServicePublicKey();
24
+ }
25
+ checkPaths() {
26
+ !fs.existsSync(_app.Core.settings.getAuthentication().certPath) && fs.mkdirSync(_app.Core.settings.getAuthentication().certPath, {
27
+ recursive: true
28
+ });
29
+ }
30
+
31
+ /* Key Pair */
32
+ async loadPrivateKey() {
33
+ const privateKeyPath = _path.default.join(_app.Core.settings.getAuthentication().certPath, 'private_key.pem');
34
+ if (fs.existsSync(privateKeyPath)) {
35
+ const pem = fs.readFileSync(privateKeyPath, 'utf8');
36
+ this.privateKey = await _nodeJose.JWK.asKey(pem, 'pem');
37
+ } else {
38
+ const {
39
+ privateKey
40
+ } = await this.createKeyPairs();
41
+ this.privateKey = await _nodeJose.JWK.asKey(privateKey, 'pem');
42
+ const pem = this.privateKey.toPEM(true);
43
+ fs.writeFileSync(privateKeyPath, pem, 'utf8');
44
+ }
45
+ }
46
+ async loadPublicKey() {
47
+ const publicKeyPath = _path.default.join(_app.Core.settings.getAuthentication().certPath, 'public_key.pem');
48
+ const pem = this.privateKey.toPEM(false);
49
+ this.publicKey = await _nodeJose.JWK.asKey(pem, 'pem');
50
+ fs.writeFileSync(publicKeyPath, pem, 'utf8');
51
+ }
52
+ async createKeyPairs() {
53
+ const keyPair = await _nodeJose.JWK.createKey('RSA', 2048, {
54
+ alg: 'RS256',
55
+ use: 'sig',
56
+ iss: _app.Core.settings.getAuthentication().issuer
57
+ });
58
+ return {
59
+ publicKey: keyPair.toPEM(false),
60
+ privateKey: keyPair.toPEM(true)
61
+ };
62
+ }
63
+ async loadServicePublicKey() {
64
+ if (fs.existsSync(_app.Core.settings.getAuthentication().servicePublicKeyPath)) {
65
+ const pem = fs.readFileSync(_app.Core.settings.getAuthentication().servicePublicKeyPath, 'utf8');
66
+ this.servicePublicKey = await _nodeJose.JWK.asKey(pem, 'pem');
67
+ } else {
68
+ throw new Error('Não foi possível localizar o certificado de serviço. Verifique o caminho nas configurações');
69
+ }
70
+ }
71
+ async loadKeyByStr(data) {
72
+ return await _nodeJose.JWK.asKey(data, 'pem');
73
+ }
74
+
75
+ /**
76
+ * Chave privada emitida por este serviço
77
+ *
78
+ * @memberof SecurityService
79
+ */
80
+ getPrivateKey() {
81
+ return this.privateKey;
82
+ }
83
+ /**
84
+ * Chave publica emitida por este serviço
85
+ *
86
+ * @memberof SecurityService
87
+ */
88
+ getPublicKey() {
89
+ return this.publicKey;
90
+ }
91
+ /**
92
+ * Chave publica emitida pelo serviço do hub se sessões
93
+ *
94
+ * @memberof SecurityService
95
+ */
96
+ getServicePublicKey() {
97
+ return this.servicePublicKey;
98
+ }
99
+ /**
100
+ * Criptografía utilizando chave publica
101
+ *
102
+ * @param {TSignData} data
103
+ * @memberof SecurityService
104
+ */
105
+ async encrypt(data, publicKey) {
106
+ const currentTime = Math.floor(Date.now() / 1000);
107
+ const defaults = {
108
+ iat: currentTime,
109
+ exp: currentTime + _app.Core.settings.getAuthentication().signExpirationSecs,
110
+ iss: _app.Core.settings.getAuthentication().issuer
111
+ };
112
+ const payload = JSON.stringify({
113
+ ...defaults,
114
+ ...data
115
+ });
116
+ try {
117
+ const encrypted = await _nodeJose.JWE.createEncrypt({
118
+ format: 'compact'
119
+ }, publicKey).update(payload).final();
120
+ return encrypted;
121
+ } catch (error) {
122
+ new _app.ErrorHandler('Não foi possível criptografar os dados', error);
123
+ return false;
124
+ }
125
+ }
126
+ /**
127
+ * Descriptografia utilizando chave privada
128
+ *
129
+ * @param {string} encryptedData
130
+ * @memberof SecurityService
131
+ */
132
+ async decrypt(encryptedData, privateKey) {
133
+ try {
134
+ const decrypted = await _nodeJose.JWE.createDecrypt(privateKey).decrypt(encryptedData);
135
+ const result = decrypted.plaintext.toString();
136
+ const parserd = JSON.parse(result);
137
+ // Tenta parsear como JSON se for objeto
138
+ return parserd.payload;
139
+ } catch (error) {
140
+ new _app.ErrorHandler('Não foi possível descriptografar os dados', error);
141
+ return false;
142
+ }
143
+ }
144
+ /**
145
+ * Realiza uma assinatura usando chave privada
146
+ *
147
+ * @param {TSignData} data
148
+ * @memberof SecurityService
149
+ */
150
+ async sign(data, privateKey) {
151
+ const currentTime = Math.floor(Date.now() / 1000);
152
+ const defaults = {
153
+ iat: currentTime,
154
+ exp: currentTime + _app.Core.settings.getAuthentication().signExpirationSecs,
155
+ iss: _app.Core.settings.getAuthentication().issuer
156
+ };
157
+ try {
158
+ const payload = JSON.stringify({
159
+ ...defaults,
160
+ ...data
161
+ });
162
+ const signature = await _nodeJose.JWS.createSign({
163
+ compact: true,
164
+ fields: {
165
+ typ: 'jwt'
166
+ }
167
+ }, privateKey).update(payload, 'utf8').final();
168
+ return signature;
169
+ } catch (error) {
170
+ new _app.ErrorHandler('Erro ao assinar os dados', error);
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Verifica assinatura utilizando chave publica
176
+ *
177
+ * @param {string} signature
178
+ * @memberof SecurityService
179
+ */
180
+ async verifySignature(signature, publicKey) {
181
+ try {
182
+ const result = await _nodeJose.JWS.createVerify(publicKey).verify(signature);
183
+ const payload = result.payload.toString();
184
+ return JSON.parse(payload);
185
+ } catch (error) {
186
+ new _app.ErrorHandler('Assinatura inválida ou erro durante a verificação', error);
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Criptografía de dados utilizando um buffer automático ao invés de chaves
192
+ *
193
+ * @param {(string | object)} data
194
+ * @memberof SecurityService
195
+ */
196
+ simpleEncrypt(data) {
197
+ if (process.versions.openssl <= '1.0.1f') {
198
+ throw new Error('OpenSSL Version too old, vulnerability to Heartbleed');
199
+ }
200
+ const key = crypto.randomBytes(32);
201
+ const iv = crypto.randomBytes(16);
202
+ const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv);
203
+ let encrypted = cipher.update(data);
204
+ encrypted = Buffer.concat([encrypted, cipher.final()]);
205
+ return [iv.toString('hex') + ':' + encrypted.toString('hex'), key];
206
+ }
207
+ /**
208
+ * Utiliza um buffer para descriptografar dados criptografados através de simpleEncrypt()
209
+ *
210
+ * @param {string} data
211
+ * @param {Buffer} key
212
+ * @memberof SecurityService
213
+ */
214
+ simpleDecrypt(data, key) {
215
+ try {
216
+ const textParts = data.split(':');
217
+ const iv = Buffer.from(textParts.shift(), 'hex');
218
+ const encryptedText = Buffer.from(textParts.join(':'), 'hex');
219
+ const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv);
220
+ let decrypted = decipher.update(encryptedText);
221
+ decrypted = Buffer.concat([decrypted, decipher.final()]);
222
+ return decrypted;
223
+ } catch (error) {
224
+ new _app.ErrorHandler('Erro durante a descriptografia de dados', error);
225
+ return false;
226
+ }
227
+ }
228
+ }
229
+ var _default = exports.default = SecurityService;
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _sequelize = require("sequelize");
8
+ var _app = require("../app");
9
+ var _service = _interopRequireDefault(require("../app/service"));
10
+ var _models = require("../models");
11
+ var _DatabaseHost = require("../models/DatabaseHost");
12
+ var _database = require("../utils/database");
13
+ var _logger = _interopRequireDefault(require("../utils/logger"));
14
+ var _security = _interopRequireDefault(require("./security"));
15
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
+ /**
17
+ * Serviço de gerênciamento do banco de dados
18
+ *
19
+ * @class SequelizeService
20
+ * @extends {Service}
21
+ * @implements {IService}
22
+ */
23
+ class SequelizeService extends _service.default {
24
+ serviceDB;
25
+ masterDB;
26
+ models;
27
+ connections;
28
+ initializedModels;
29
+ relations;
30
+
31
+ //# Initialization
32
+ constructor() {
33
+ super();
34
+ }
35
+ async init() {
36
+ this.serviceDB = _database.serviceDB;
37
+ this.masterDB = _database.masterDB;
38
+ this.connections = new Map();
39
+ this.initializedModels = new Map();
40
+ this.relations = new Map();
41
+ await this.connectDatabases();
42
+ }
43
+ async connectDatabases() {
44
+ if (!this.models) throw new Error('Models are requireds! Call registerModels(modelsArray)');
45
+
46
+ // #Include native models
47
+ this.models = [...this.models, ..._models.NativeModels];
48
+ return new Promise((resolve, reject) => {
49
+ this.masterDB.sync({
50
+ force: false
51
+ }).then(() => {
52
+ this.log('✅ Connected master database sucessfully', 'success');
53
+ this.serviceDB.sync({
54
+ force: false
55
+ }).then(() => {
56
+ this.log('✅ Connected service database sucessfully', 'success');
57
+ resolve(true);
58
+ }).catch(reason => {
59
+ new _app.ErrorHandler('Não foi possível inicializar a conexão com o ServiceDB', reason);
60
+ reject(reason);
61
+ });
62
+ }).catch(reason => {
63
+ new _app.ErrorHandler('Não foi possível inicializar a conexão com MasterDB', reason);
64
+ reject(reason);
65
+ });
66
+ });
67
+ }
68
+
69
+ // #Database
70
+ async getDB(tenantId) {
71
+ /* master or service */
72
+ if (tenantId == _app.Core.settings.getDatabase().service.database) {
73
+ return _database.serviceDB;
74
+ } else if (tenantId == _app.Core.settings.getDatabase().master.database) {
75
+ return _database.masterDB;
76
+ }
77
+ const relation = await this.getRelation(tenantId);
78
+ if (!relation) return false;
79
+ const key = `${relation.hostUuid}@${this.getDBName(relation.envToken)}`;
80
+ return this.connections.get(key) || (await this.initDB(tenantId));
81
+ }
82
+ async createDB(hostUuid, name) {
83
+ const host = await _DatabaseHost.DatabaseHost.findByPk(hostUuid);
84
+ if (!host) {
85
+ this.log('Database host information not found: ' + hostUuid);
86
+ return false;
87
+ }
88
+ const dbQueryName = `${_app.Core.settings.getDatabase().service.database}_${name}`;
89
+ const connection = await this.createConnection(hostUuid);
90
+ if (connection) {
91
+ try {
92
+ const [results] = await connection.query(`SHOW DATABASES LIKE '${dbQueryName}';`);
93
+ if (results.length === 0) {
94
+ // Se o banco de dados não existir, cria-o
95
+ await connection.query(`CREATE DATABASE ${dbQueryName};`);
96
+ this.log(`Database "${dbQueryName}" has been created.`);
97
+ return true;
98
+ } else {
99
+ this.log(`Database "${dbQueryName}" already exists.`);
100
+ return false;
101
+ }
102
+ } catch (error) {
103
+ new _app.ErrorHandler('Erro on creating database', error);
104
+ } finally {
105
+ connection.close();
106
+ }
107
+ }
108
+ return false;
109
+ }
110
+ async hasDB(hostUuid, name) {
111
+ const host = await _DatabaseHost.DatabaseHost.findByPk(hostUuid);
112
+ if (!host) {
113
+ this.log('Database host information not found: ' + hostUuid);
114
+ return false;
115
+ }
116
+ const dbQueryName = `${_app.Core.settings.getDatabase().service.database}_${name}`;
117
+ const connection = await this.createConnection(hostUuid);
118
+ if (connection) {
119
+ try {
120
+ const [results] = await connection.query(`SHOW DATABASES LIKE '${dbQueryName}';`);
121
+ return results.length > 0;
122
+ } catch (error) {
123
+ new _app.ErrorHandler('Erro on creating database', error);
124
+ } finally {
125
+ connection.close();
126
+ }
127
+ }
128
+ return false;
129
+ }
130
+ async deleteDB(hostUuid, name) {
131
+ const dbQueryName = `${_app.Core.settings.getDatabase().service.database}_${name}`;
132
+ const connection = await this.createConnection(hostUuid);
133
+ if (connection) {
134
+ try {
135
+ await connection.query(`DROP DATABASE IF EXISTS ${dbQueryName};`);
136
+ this.log(`Database "${dbQueryName}" has been deleted.`);
137
+ return true;
138
+ } catch (error) {
139
+ return false;
140
+ } finally {
141
+ connection.close();
142
+ }
143
+ }
144
+ return false;
145
+ }
146
+ async initDB(tenantId) {
147
+ const relation = await this.getRelation(tenantId);
148
+ if (!relation) return false;
149
+ const dbName = this.getDBName(relation.envToken);
150
+ const key = `${relation.hostUuid}@${this.getDBName(relation.envToken)}`;
151
+ if (this.connections.has(key)) return this.connections.get(key);
152
+ const connection = await this.createConnection(relation.hostUuid, dbName);
153
+ if (connection) {
154
+ this.log(`✅ Connected ${dbName} database sucessfully`, 'success');
155
+ this.connections.set(key, connection);
156
+ return connection;
157
+ }
158
+ }
159
+ getDBName(envToken) {
160
+ return `${_app.Core.settings.getDatabase().service.database}_${envToken}`;
161
+ }
162
+
163
+ //#Connection
164
+ reconnect(db, attempts = 2) {
165
+ db.sync().then(() => {
166
+ this.log('Database pronto', 'success');
167
+ }).catch(reason => {
168
+ this.log('Attemping to connect master database', 'warning');
169
+ (0, _logger.default)().warn('Erro ao inicializar o banco de dados, tentando novamente...', reason);
170
+ if (attempts > 0) {
171
+ setTimeout(() => this.reconnect(db, attempts - 1), 5000);
172
+ } else {
173
+ new _app.ErrorHandler('Error on connecting master database', reason);
174
+ }
175
+ });
176
+ }
177
+ async createConnection(hostUuid, database) {
178
+ const host = await _DatabaseHost.DatabaseHost.findByPk(hostUuid);
179
+ if (!host) {
180
+ this.log('createConnection:: Database host information not found: ' + hostUuid);
181
+ return false;
182
+ }
183
+ const key = await _security.default.singleton().loadKeyByStr(host.credential);
184
+ const data = await _security.default.singleton().verifySignature(host.password, key);
185
+ if (!data) {
186
+ this.log('createConnection::Error on decript password by credential: ' + hostUuid, 'danger');
187
+ return false;
188
+ }
189
+ const password = data.payload;
190
+ const queryHost = host.host.split(':');
191
+ const sequelize = new _sequelize.Sequelize({
192
+ host: queryHost[0],
193
+ port: Number(queryHost[1]),
194
+ dialect: host.dialect,
195
+ database,
196
+ username: host.username,
197
+ password: password,
198
+ define: {
199
+ timestamps: true
200
+ },
201
+ timezone: '-03:00',
202
+ logging(sql, timing) {
203
+ (0, _logger.default)().trace('DATABASE', sql, timing);
204
+ }
205
+ });
206
+ return new Promise((resolve, reject) => {
207
+ sequelize.authenticate().then(async () => {
208
+ resolve(sequelize);
209
+ }).catch(reason => {
210
+ reject(reason);
211
+ });
212
+ });
213
+ }
214
+ async testConnection(data) {
215
+ const sequelize = new _sequelize.Sequelize({
216
+ host: data.host,
217
+ port: data.port,
218
+ username: data.username,
219
+ password: data.password,
220
+ dialect: data.dialect,
221
+ timezone: '-03:00',
222
+ logging(sql, timing) {
223
+ (0, _logger.default)().trace('DATABASE', sql, timing);
224
+ }
225
+ });
226
+ return new Promise(resolve => {
227
+ sequelize.authenticate().then(async () => {
228
+ resolve(true);
229
+ }).catch(reason => {
230
+ new _app.ErrorHandler('teste de conexão falhou', reason);
231
+ resolve(false);
232
+ }).finally(() => {
233
+ sequelize.close();
234
+ });
235
+ });
236
+ }
237
+
238
+ //# Common
239
+ async getRelation(tenantId) {
240
+ let relation;
241
+ /* fetch relation */
242
+ if (this.relations.get(tenantId)) {
243
+ relation = this.relations.get(tenantId);
244
+ } else {
245
+ relation = await _models.EnvDBHost.findOne({
246
+ where: {
247
+ envUuid: tenantId
248
+ }
249
+ });
250
+ if (relation) {
251
+ this.relations.set(tenantId, relation);
252
+ }
253
+ }
254
+ return relation;
255
+ }
256
+
257
+ // #Entity
258
+ async getModel(model, tenantId) {
259
+ try {
260
+ let connection = false;
261
+ const modelKey = `${tenantId}#${model.name}`;
262
+ if (tenantId == _app.Core.settings.getDatabase().service.database) {
263
+ connection = _database.serviceDB;
264
+ } else if (tenantId == _app.Core.settings.getDatabase().master.database) {
265
+ connection = _database.masterDB;
266
+ } else {
267
+ connection = await this.getDB(tenantId);
268
+ }
269
+ if (this.initializedModels.has(modelKey)) return this.initializedModels.get(modelKey);
270
+ if (!connection) {
271
+ throw new Error('Conexão não encontrada');
272
+ }
273
+ const m = model.initialize(connection);
274
+ await m.sync();
275
+ this.initializedModels.set(modelKey, m);
276
+ return m;
277
+ } catch (error) {
278
+ throw new _app.ErrorHandler('Erro ao obter o model', error);
279
+ }
280
+ }
281
+ registerModels(models) {
282
+ this.models = models;
283
+ }
284
+ }
285
+ var _default = exports.default = SequelizeService;