@everneed/worker 1.1.0 → 2.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.
- package/index.js +1 -1
- package/package.json +1 -1
- package/worker/rabbitmq.js +536 -76
package/index.js
CHANGED
|
@@ -89,6 +89,6 @@ import pseudoEnv from "./pseudoenv.js"
|
|
|
89
89
|
|
|
90
90
|
export { rabbitmq } // preserve seperate-dir for example
|
|
91
91
|
export { postgresInstance as postgres }
|
|
92
|
-
|
|
92
|
+
export { mongooseInstance as mongoose }
|
|
93
93
|
export { redisInstance as redis }
|
|
94
94
|
export { socketioInstance as socketio }
|
package/package.json
CHANGED
package/worker/rabbitmq.js
CHANGED
|
@@ -1,26 +1,212 @@
|
|
|
1
1
|
import path from "path"
|
|
2
2
|
import fs from "fs"
|
|
3
|
+
import crypto from "crypto"
|
|
3
4
|
import amqp from "amqplib/callback_api.js"
|
|
4
5
|
import moment from "moment"
|
|
5
6
|
|
|
6
7
|
import pseudoEnv from "@everneed/worker/pseudoenv.js"
|
|
7
8
|
import { createHmac } from "crypto"
|
|
9
|
+
import { redis } from "@everneed/worker"
|
|
10
|
+
import { ResponseCode } from "@everneed/responsecode"
|
|
11
|
+
import { pipe, switchPourStr, randomStr } from "@everneed/helper"
|
|
12
|
+
|
|
13
|
+
class VersionManager{
|
|
14
|
+
#currentVer
|
|
15
|
+
#deprecated
|
|
16
|
+
#configPath = null
|
|
17
|
+
#endpointMap
|
|
18
|
+
|
|
19
|
+
// 🗑️
|
|
20
|
+
#existingBucket = []
|
|
21
|
+
#loadedBucket = []
|
|
22
|
+
|
|
23
|
+
constructor(){
|
|
24
|
+
this.init()
|
|
25
|
+
this.#load()
|
|
26
|
+
}
|
|
27
|
+
init(){
|
|
28
|
+
this.#load()
|
|
29
|
+
}
|
|
30
|
+
config(configPath){
|
|
31
|
+
this.#configPath = path.join("../../..", configPath)
|
|
32
|
+
|
|
33
|
+
/* Re-init */
|
|
34
|
+
this.init()
|
|
35
|
+
}
|
|
36
|
+
#clean(){
|
|
37
|
+
this.#currentVer = null
|
|
38
|
+
this.#configPath = null
|
|
39
|
+
this.#endpointMap = {}
|
|
40
|
+
this.#existingBucket = []
|
|
41
|
+
this.#loadedBucket = []
|
|
42
|
+
}
|
|
43
|
+
#load(){
|
|
44
|
+
// json into endpointMaps
|
|
45
|
+
let json
|
|
46
|
+
if(!this.#configPath){
|
|
47
|
+
try{
|
|
48
|
+
// json = require("../../config/versionmap.json")
|
|
49
|
+
json = fs.readFileSync(path.join(process.cwd(), "/config/versionmap.json"))
|
|
50
|
+
}
|
|
51
|
+
catch(err){
|
|
52
|
+
json = `{"/endpoint/one":{"latest": 1, "map":{"1":1}}}`
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else{
|
|
56
|
+
json = fs.readFileSync(path.resolve(this.#configPath))
|
|
57
|
+
const fs = require("fs")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const config = pipe(json)
|
|
61
|
+
.then(json=> JSON.parse(json))
|
|
62
|
+
.result
|
|
63
|
+
this.#endpointMap = config.endpoint
|
|
64
|
+
this.#currentVer = config.apiVer
|
|
65
|
+
this.#deprecated = config.deprecatedVer
|
|
66
|
+
}
|
|
67
|
+
async update(){
|
|
68
|
+
// Define new version
|
|
69
|
+
const newVer = this.#currentVer+1
|
|
70
|
+
// Load all existing running API and stage them
|
|
71
|
+
// in existingBucket
|
|
72
|
+
const files = fs.readdirSync(`./src/mq-gateway`)
|
|
73
|
+
for(const file of files){
|
|
74
|
+
const module = file.replace(/.js|.ts/g, ``).toLowerCase()
|
|
75
|
+
const functs = await import(`file://${path.join(process.cwd(), `/src/mq-gateway/${file}`)}`)
|
|
76
|
+
|
|
77
|
+
for(const funct in functs.default){
|
|
78
|
+
for(const ver in functs.default[funct].function){
|
|
79
|
+
this.#existingBucket.push(`/${pseudoEnv.process.env.SVC_NAME}/${module}/${funct}/${ver}`)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Prep irregular changes and unchanges 🔪🌽🍍🥕
|
|
85
|
+
// into more consumable iterable form
|
|
86
|
+
// will output the elements from existing bucket that are not in the loaded bucket
|
|
87
|
+
const addition = this.#existingBucket.filter(x => !this.#loadedBucket.includes(x))
|
|
88
|
+
const updation = pipe(addition)
|
|
89
|
+
.then(addition=>{
|
|
90
|
+
return {
|
|
91
|
+
addition: addition.map(fullEndpoint=> fullEndpoint.split(/\/v([0-9]+)$/, 2)[0]),
|
|
92
|
+
all: this.#existingBucket.map(fullEndpoint=> fullEndpoint.split(/\/v([0-9]+)$/, 2)[0])
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
.then(({addition, all})=> new Set(all).difference(new Set(addition)))
|
|
96
|
+
.then(set=> [...set])
|
|
97
|
+
.result
|
|
98
|
+
|
|
99
|
+
// Process to then stash result to head variable 🥣
|
|
100
|
+
for(const endpoint of addition){
|
|
101
|
+
// "/endpoint/one/v1" -> [/endpoint/one, 1]
|
|
102
|
+
const [pureEndpoint, versionInt] = endpoint.split(/\/v([0-9]+)$/, 2)
|
|
103
|
+
|
|
104
|
+
// new endpoint
|
|
105
|
+
if(!this.#endpointMap[pureEndpoint]){
|
|
106
|
+
this.#endpointMap[pureEndpoint] = {
|
|
107
|
+
latest: 1,
|
|
108
|
+
map: {}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
this.#endpointMap[pureEndpoint]["map"][`v${newVer}`] = 1
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.#endpointMap[pureEndpoint].latest = Number(versionInt)
|
|
115
|
+
this.#endpointMap[pureEndpoint].map[`v${newVer}`] = Number(versionInt)
|
|
116
|
+
// /pure/endpoint:{
|
|
117
|
+
// latest: (2), <--- updated
|
|
118
|
+
// map:{
|
|
119
|
+
// v1: 1,
|
|
120
|
+
// v2: 1,
|
|
121
|
+
// v3: 2 <-- addition
|
|
122
|
+
// }
|
|
123
|
+
// }
|
|
124
|
+
}
|
|
125
|
+
for(const endpoint in updation){
|
|
126
|
+
this.#endpointMap[endpoint].map[`v${newVer}`] = this.#endpointMap[endpoint].latest
|
|
127
|
+
// /pure/endpoint:{
|
|
128
|
+
// latest: 1,
|
|
129
|
+
// map:{
|
|
130
|
+
// v1: 1,
|
|
131
|
+
// v2: 1,
|
|
132
|
+
// v3: 1 <-- updated
|
|
133
|
+
// }
|
|
134
|
+
// }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Save head variable into config file (.json)
|
|
138
|
+
const json = JSON.stringify({
|
|
139
|
+
apiVer: newVer,
|
|
140
|
+
lastUpdate: moment().utc().format(),
|
|
141
|
+
endpoint: this.#endpointMap
|
|
142
|
+
}, null, 4)
|
|
143
|
+
if(!this.#configPath){
|
|
144
|
+
try{
|
|
145
|
+
fs.writeFileSync(path.join(process.cwd(), "/config/versionmap.json"), json)
|
|
146
|
+
}
|
|
147
|
+
catch(err){
|
|
148
|
+
console.log(err)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else{
|
|
152
|
+
fs.writeFileSync(path.resolve(__dirname, this.#configPath), json)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// re-load
|
|
156
|
+
this.#clean()
|
|
157
|
+
this.#load()
|
|
158
|
+
}
|
|
159
|
+
allVersion(endpoint){
|
|
160
|
+
// returns array of available version map
|
|
161
|
+
// in respecting order (index 0 should be null)
|
|
162
|
+
// Array due to be iterated nature
|
|
163
|
+
|
|
164
|
+
const result = [null]
|
|
165
|
+
|
|
166
|
+
for(const majorVer in this.#endpointMap[endpoint].map){
|
|
167
|
+
result[majorVer] = this.#endpointMap[endpoint].map[majorVer] // major = individual
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return result // [null, individual ver, individual ver]
|
|
171
|
+
}
|
|
172
|
+
trueVersion({endpoint, version}){
|
|
173
|
+
return this.#endpointMap[endpoint].map[`v${version}`]
|
|
174
|
+
}
|
|
175
|
+
latestVersion(){
|
|
176
|
+
return this.#currentVer
|
|
177
|
+
}
|
|
178
|
+
deprecatedVersion(){
|
|
179
|
+
return this.#deprecated
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const version = new VersionManager()
|
|
183
|
+
version.init()
|
|
8
184
|
|
|
9
185
|
export default {
|
|
10
|
-
config: (object)
|
|
186
|
+
config: function(object){
|
|
11
187
|
// config({
|
|
12
188
|
// ENV: value,
|
|
13
189
|
// ...
|
|
14
190
|
// })
|
|
15
191
|
/* Param Validation */
|
|
16
|
-
const allowed = new Set([
|
|
192
|
+
const allowed = new Set([
|
|
193
|
+
"SVC_NAME",
|
|
194
|
+
"SVC_DISPLAY",
|
|
195
|
+
"RABBIT_HOST",
|
|
196
|
+
"RABBIT_MESSAGE_KEY",
|
|
197
|
+
"RABBIT_MESSAGE_IV",
|
|
198
|
+
"RABBIT_MESSAGE_SALT",
|
|
199
|
+
"TOKEN_UA_SALT",
|
|
200
|
+
"TOKEN_KEY",
|
|
201
|
+
"TOKEN_IV"
|
|
202
|
+
])
|
|
17
203
|
if(new Set(Object.keys(object)).difference(allowed).size){
|
|
18
204
|
throw `illegal key on rabbitmq.config(): Only ${Array.from(allowed).join(", ")} are allowed`
|
|
19
205
|
}
|
|
20
206
|
/* Env Add Process */
|
|
21
207
|
pseudoEnv.config(object)
|
|
22
208
|
},
|
|
23
|
-
start: ()
|
|
209
|
+
start: function(){
|
|
24
210
|
/* RabbitMQ Engine */
|
|
25
211
|
amqp.connect(pseudoEnv.process.env.RABBIT_HOST, async (error0, connection)=>{
|
|
26
212
|
if(error0) throw error0
|
|
@@ -41,24 +227,106 @@ export default {
|
|
|
41
227
|
const main = await import(`file://${path.join(process.cwd(), `/src/mq-gateway/${moduleSpace}`)}.js`)
|
|
42
228
|
// const main = await import(`#@/mq-gateway/${moduleSpace}.js`)
|
|
43
229
|
|
|
44
|
-
for(const
|
|
230
|
+
for(const endpoint in main.default){
|
|
45
231
|
/* Generate consumer */
|
|
46
|
-
channel.assertQueue(`req/${pseudoEnv.process.env.SVC_NAME}/${moduleSpace}/${
|
|
232
|
+
channel.assertQueue(`req/${pseudoEnv.process.env.SVC_NAME}/${moduleSpace}/${endpoint}`, {
|
|
47
233
|
durable: true
|
|
48
234
|
})
|
|
49
|
-
channel.consume(`req/${pseudoEnv.process.env.SVC_NAME}/${moduleSpace}/${
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
.
|
|
53
|
-
.
|
|
235
|
+
channel.consume(`req/${pseudoEnv.process.env.SVC_NAME}/${moduleSpace}/${endpoint}`, async (message)=>{
|
|
236
|
+
const mqHeader = message.properties.headers
|
|
237
|
+
const mqReq = await this.decryptMessage({
|
|
238
|
+
mode: mqHeader.mode,
|
|
239
|
+
message: message.content.toString(),
|
|
240
|
+
...(mqHeader.auth && { token: mqHeader.auth.token }),
|
|
241
|
+
...(mqHeader.auth && { userAgent: mqHeader.auth.userAgent })
|
|
242
|
+
})
|
|
243
|
+
const trueVersion = mqHeader.version ?
|
|
244
|
+
version.trueVersion({
|
|
245
|
+
endpoint: `/${pseudoEnv.process.env.SVC_NAME}/${moduleSpace}/${endpoint}`,
|
|
246
|
+
version: mqHeader.version
|
|
247
|
+
})
|
|
248
|
+
:
|
|
249
|
+
version.latestVersion()
|
|
54
250
|
|
|
55
|
-
const
|
|
251
|
+
const prep = {
|
|
252
|
+
message: null
|
|
253
|
+
}
|
|
56
254
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
255
|
+
try{
|
|
256
|
+
/* Active Endpoint Filter */
|
|
257
|
+
if(!main.default[endpoint].active){
|
|
258
|
+
const response = new ResponseCode()
|
|
259
|
+
response.pushCode("INVALID_ENDPOINT")
|
|
260
|
+
prep["message"] = await this.encryptMessage({
|
|
261
|
+
mode: mqHeader.mode,
|
|
262
|
+
message: response.result
|
|
263
|
+
})
|
|
264
|
+
throw "invalid_endpoint"
|
|
265
|
+
}
|
|
266
|
+
/* API enforce Auth */
|
|
267
|
+
if(main.default[endpoint].authentication){
|
|
268
|
+
if(!mqHeader.auth && mqHeader.mode != "auth"){
|
|
269
|
+
const response = new ResponseCode()
|
|
270
|
+
response.pushCode("NOT_AUTHENTICATED")
|
|
271
|
+
prep["message"] = await this.encryptMessage({
|
|
272
|
+
mode: mqHeader.mode,
|
|
273
|
+
message: response.result
|
|
274
|
+
})
|
|
275
|
+
throw "not_authenticated"
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* With Auth */
|
|
280
|
+
if(mqHeader.auth && mqHeader.mode == "auth"){
|
|
281
|
+
const { token, userAgent } = mqHeader.auth
|
|
282
|
+
const auth = await this.verifyToken({
|
|
283
|
+
token: token,
|
|
284
|
+
userAgent: userAgent
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
if(auth.checkError()){ // NOT_AUTHENTICATED || SESSION_EXPIRED
|
|
288
|
+
prep["message"] = await this.encryptMessage({
|
|
289
|
+
mode: mqHeader.mode,
|
|
290
|
+
message: auth.result
|
|
291
|
+
})
|
|
292
|
+
}
|
|
293
|
+
else{ // AUTHENTICATED || REFRESH_SESSION
|
|
294
|
+
const result = await main.default[endpoint].function[`v${trueVersion}`](mqHeader.auth, mqReq.payload)
|
|
295
|
+
const response = new ResponseCode(result)
|
|
296
|
+
if(auth.hasCode("REFRESH_SESSION")) response.pushRefresh(auth.result.data)
|
|
297
|
+
prep["message"] = await this.encryptMessage({
|
|
298
|
+
mode: mqHeader.mode,
|
|
299
|
+
message: response.result,
|
|
300
|
+
token: token,
|
|
301
|
+
userAgent: userAgent
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/* Without Auth */
|
|
306
|
+
else{
|
|
307
|
+
const result = await main.default[endpoint].function[`v${trueVersion}`](false, mqReq.payload)
|
|
308
|
+
prep["message"] = await this.encryptMessage({
|
|
309
|
+
mode: mqHeader.mode,
|
|
310
|
+
message: result,
|
|
311
|
+
...(mqHeader.auth && { token: mqHeader.auth.token }),
|
|
312
|
+
...(mqHeader.auth && { userAgent: mqHeader.auth.userAgent })
|
|
313
|
+
})
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
throw "finish"
|
|
317
|
+
}
|
|
318
|
+
catch(something){
|
|
319
|
+
if(mqReq.trip == "returning"){
|
|
320
|
+
channel.sendToQueue(message.properties.replyTo, Buffer.from(prep.message), {
|
|
321
|
+
correlationId: message.properties.correlationId,
|
|
322
|
+
headers:{
|
|
323
|
+
mode: mqHeader.mode,
|
|
324
|
+
...(mqHeader.version && { version: mqHeader.version }),
|
|
325
|
+
...(mqHeader.auth && { auth: mqHeader.auth })
|
|
326
|
+
},
|
|
327
|
+
})
|
|
328
|
+
channel.ack(message)
|
|
329
|
+
}
|
|
62
330
|
}
|
|
63
331
|
},{
|
|
64
332
|
noAck: false
|
|
@@ -69,91 +337,283 @@ export default {
|
|
|
69
337
|
// connection.close()
|
|
70
338
|
})
|
|
71
339
|
},
|
|
72
|
-
publish: ({topic,
|
|
340
|
+
publish: function({topic, version, mode="auth", auth=null, trip="passby", data}){
|
|
73
341
|
/* Usage */
|
|
74
342
|
// publish({
|
|
75
343
|
// topic: <topic start at svc :String>,
|
|
76
|
-
//
|
|
344
|
+
// mode: <"auth"|"no auth" :String>
|
|
345
|
+
// auth:{
|
|
346
|
+
// token: <auth token :String>,
|
|
347
|
+
// userAgent: <ua string :String>,
|
|
348
|
+
// }
|
|
77
349
|
// trip: <"returning"|"passby" :String>,
|
|
78
350
|
// data: <message :String>
|
|
79
351
|
// })
|
|
80
352
|
|
|
81
353
|
// topic: <req|res>/<short sha username + random string>/<svc>/<endpoint>
|
|
82
|
-
// ex: req/cd6f01UjkB7E/rolling-tempat-duduk/class/
|
|
83
|
-
// ex: res/cd6f01UjkB7E/rolling-tempat-duduk/class/
|
|
354
|
+
// ex: req/cd6f01UjkB7E/rolling-tempat-duduk/class/getAll
|
|
355
|
+
// ex: res/cd6f01UjkB7E/rolling-tempat-duduk/class/getAll
|
|
84
356
|
|
|
85
357
|
return new Promise(async (resolve, reject)=>{
|
|
86
358
|
/* RabbitMQ Engine */
|
|
87
|
-
amqp.connect(pseudoEnv.process.env.RABBIT_HOST, (error0, connection)=>{
|
|
359
|
+
amqp.connect(pseudoEnv.process.env.RABBIT_HOST, async (error0, connection)=>{
|
|
88
360
|
if(error0){ throw error0 }
|
|
89
361
|
|
|
90
362
|
/* Creates connection & channel */
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
})
|
|
363
|
+
const channel = connection.createChannel((error1, channel)=>{
|
|
364
|
+
if (error1){ throw error1 }
|
|
365
|
+
return channel
|
|
366
|
+
})
|
|
96
367
|
|
|
97
368
|
/* Build payload structure */
|
|
98
369
|
// like topic, address, etc.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
370
|
+
const userName = auth ? this.getUserInfo({tokenBody: auth.token.split(".")[0]}).userName : `guest${randomStr({length: 12})}`
|
|
371
|
+
const prep = {
|
|
372
|
+
topic: `req/${topic}`,
|
|
373
|
+
message:{
|
|
374
|
+
trip: trip,
|
|
375
|
+
senderAddress: `${createHmac("sha256", userName).digest("hex").slice(0, 12)}${moment().utc().format("HHmmssSSS")}`,
|
|
376
|
+
payload: data
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
/* Main publisher */
|
|
380
|
+
const mqReq = await this.encryptMessage({
|
|
381
|
+
mode: mode,
|
|
382
|
+
message: prep.message,
|
|
383
|
+
...(auth && { token: auth.token }),
|
|
384
|
+
...(auth && { userAgent: auth.userAgent })
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
channel.assertQueue(prep.topic, { durable: true })
|
|
388
|
+
channel.sendToQueue(prep.topic, Buffer.from(mqReq), {
|
|
389
|
+
headers:{
|
|
390
|
+
...(version && { version: version }),
|
|
391
|
+
mode: mode,
|
|
392
|
+
...(auth && { auth: auth })
|
|
393
|
+
},
|
|
394
|
+
...(trip == "returning" && { correlationId: prep.message.senderAddress }),
|
|
395
|
+
...(trip == "returning" && { replyTo: `res/${topic}` }),
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
/* Resolvation According to Trip */
|
|
399
|
+
if(trip == "returning"){
|
|
400
|
+
/* Creates consumer for returning messages */
|
|
401
|
+
channel.assertQueue(`res/${topic}`, { durable: true })
|
|
402
|
+
channel.consume(`res/${topic}`, async (message)=>{
|
|
403
|
+
/* Differentiate normal flow with refresh session flow */
|
|
404
|
+
const sessionRefresh = ()=>{
|
|
405
|
+
const response = new ResponseCode(message.content.toString())
|
|
406
|
+
if(response.hasCode("REFRESH_SESSION")) return true
|
|
407
|
+
else return false
|
|
408
|
+
}
|
|
409
|
+
const mqRes = await this.decryptMessage({
|
|
410
|
+
mode: mode,
|
|
411
|
+
message: message.content.toString(),
|
|
412
|
+
...((auth && !sessionRefresh()) && { token: auth.token }),
|
|
413
|
+
...((auth && sessionRefresh()) && { token: message.content.toString().data.token }),
|
|
414
|
+
...(auth && { userAgent: auth.userAgent })
|
|
415
|
+
})
|
|
118
416
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
417
|
+
if(message.properties.correlationId == prep.message.senderAddress){
|
|
418
|
+
resolve(mqRes)
|
|
419
|
+
channel.ack(message)
|
|
420
|
+
setTimeout(()=>{
|
|
421
|
+
connection.close()
|
|
422
|
+
}, 500)
|
|
423
|
+
}
|
|
424
|
+
}, {
|
|
425
|
+
noAck: false
|
|
426
|
+
})
|
|
427
|
+
}
|
|
428
|
+
else if(trip == "passby"){
|
|
429
|
+
resolve("sent")
|
|
430
|
+
|
|
122
431
|
setTimeout(()=>{
|
|
123
432
|
connection.close()
|
|
124
433
|
}, 500)
|
|
125
434
|
}
|
|
126
|
-
}, {
|
|
127
|
-
noAck: false
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
/* Main publisher (with correlation id) */
|
|
131
|
-
channel.assertQueue(prep.topic,{
|
|
132
|
-
durable: true
|
|
133
|
-
})
|
|
134
|
-
channel.sendToQueue(prep.topic, Buffer.from(JSON.stringify(prep.message)), {
|
|
135
|
-
correlationId: prep.message.senderAddress,
|
|
136
|
-
replyTo: resTopic
|
|
137
|
-
})
|
|
138
|
-
}
|
|
139
|
-
else if(trip == "passby"){
|
|
140
|
-
/* Main publisher */
|
|
141
|
-
// pushes without senderAddress
|
|
142
|
-
prep.message["senderAddress"] = null
|
|
143
|
-
|
|
144
|
-
channel.assertQueue(prep.topic,{
|
|
145
|
-
durable: true
|
|
146
|
-
})
|
|
147
|
-
channel.sendToQueue(prep.topic, Buffer.from(JSON.stringify(prep.message)))
|
|
148
|
-
resolve("sent")
|
|
149
|
-
|
|
150
|
-
setTimeout(()=>{
|
|
151
|
-
connection.close()
|
|
152
|
-
}, 500)
|
|
153
|
-
}
|
|
154
435
|
|
|
155
436
|
// connection.close()
|
|
156
437
|
})
|
|
157
438
|
})
|
|
158
439
|
},
|
|
440
|
+
encryptMessage: function({mode="auth", message, token=null, userAgent=null}){
|
|
441
|
+
return new Promise(async (resolve, reject)=>{
|
|
442
|
+
if(mode == "auth"){
|
|
443
|
+
/* Active Auth Session */
|
|
444
|
+
if(token && userAgent){
|
|
445
|
+
const { userId } = this.getUserInfo({ tokenBody: token.split(".")[0] })
|
|
446
|
+
const uaHash = crypto.hash("sha256", switchPourStr(userAgent, pseudoEnv.process.env.TOKEN_UA_SALT))
|
|
447
|
+
await redis.connect().catch(error => {})
|
|
448
|
+
const authKey = await redis.get(`auth:session:long:${userId}:${uaHash}`)
|
|
449
|
+
const hash = crypto.hash("sha256", switchPourStr(authKey, pseudoEnv.process.env.RABBIT_MESSAGE_SALT))
|
|
450
|
+
const key = hash.substring(0, 16)
|
|
451
|
+
const iv = hash.substring(48)
|
|
452
|
+
|
|
453
|
+
const cipher = crypto.createCipheriv("aes-128-cbc", Buffer.from(key), Buffer.from(iv))
|
|
454
|
+
let encrypted = cipher.update(JSON.stringify(message), "utf-8", "base64")
|
|
455
|
+
encrypted += cipher.final("base64")
|
|
456
|
+
return resolve(encrypted)
|
|
457
|
+
}
|
|
458
|
+
/* No Auth */
|
|
459
|
+
else{
|
|
460
|
+
const cipher = crypto.createCipheriv("aes-128-cbc", Buffer.from(pseudoEnv.process.env.RABBIT_MESSAGE_KEY), Buffer.from(pseudoEnv.process.env.RABBIT_MESSAGE_IV))
|
|
461
|
+
let encrypted = cipher.update(JSON.stringify(message), "utf-8", "base64")
|
|
462
|
+
encrypted += cipher.final("base64")
|
|
463
|
+
return resolve(encrypted)
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
else if(mode == "no auth"){
|
|
467
|
+
/* Unchecked Token (Illegal/Refresh) */
|
|
468
|
+
if(token){
|
|
469
|
+
const {key, iv} = pipe(token)
|
|
470
|
+
.then(token=> token.split(".")[0])
|
|
471
|
+
.then(tokenBody=> this.getUserInfo({tokenBody: tokenBody}))
|
|
472
|
+
.then(({userName, userId, displayName})=>{
|
|
473
|
+
return switchPourStr(
|
|
474
|
+
userName,
|
|
475
|
+
pseudoEnv.process.env.RABBIT_MESSAGE_KEY,
|
|
476
|
+
userId,
|
|
477
|
+
pseudoEnv.process.env.RABBIT_MESSAGE_IV,
|
|
478
|
+
displayName,
|
|
479
|
+
)
|
|
480
|
+
})
|
|
481
|
+
.then(mixWord=> crypto.hash("sha256", mixWord))
|
|
482
|
+
.then(hash=>{
|
|
483
|
+
return {
|
|
484
|
+
key: hash.substring(0, 16),
|
|
485
|
+
iv: hash.substring(48)
|
|
486
|
+
}
|
|
487
|
+
})
|
|
488
|
+
.result
|
|
489
|
+
|
|
490
|
+
const cipher = crypto.createCipheriv("aes-128-cbc", Buffer.from(key), Buffer.from(iv))
|
|
491
|
+
let encrypted = cipher.update(JSON.stringify(message), "utf-8", "base64")
|
|
492
|
+
encrypted += cipher.final("base64")
|
|
493
|
+
return resolve(encrypted)
|
|
494
|
+
}
|
|
495
|
+
/* No Auth */
|
|
496
|
+
else{
|
|
497
|
+
const cipher = crypto.createCipheriv("aes-128-cbc", Buffer.from(pseudoEnv.process.env.RABBIT_MESSAGE_KEY), Buffer.from(pseudoEnv.process.env.RABBIT_MESSAGE_IV))
|
|
498
|
+
let encrypted = cipher.update(JSON.stringify(message), "utf-8", "base64")
|
|
499
|
+
encrypted += cipher.final("base64")
|
|
500
|
+
return resolve(encrypted)
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
})
|
|
504
|
+
},
|
|
505
|
+
decryptMessage: function({mode="auth", message, token=null, userAgent=null}){
|
|
506
|
+
return new Promise(async (resolve, reject)=>{
|
|
507
|
+
if(mode == "auth"){
|
|
508
|
+
/* Active Auth Session */
|
|
509
|
+
if(token && userAgent){
|
|
510
|
+
const { userId } = this.getUserInfo({ tokenBody: token.split(".")[0] })
|
|
511
|
+
const uaHash = crypto.hash("sha256", switchPourStr(userAgent, pseudoEnv.process.env.TOKEN_UA_SALT))
|
|
512
|
+
await redis.connect().catch(error => {})
|
|
513
|
+
const authKey = await redis.get(`auth:session:long:${userId}:${uaHash}`)
|
|
514
|
+
const hash = crypto.hash("sha256", switchPourStr(authKey, pseudoEnv.process.env.RABBIT_MESSAGE_SALT))
|
|
515
|
+
const key = hash.substring(0, 16)
|
|
516
|
+
const iv = hash.substring(48)
|
|
517
|
+
|
|
518
|
+
const decipher = crypto.createDecipheriv("aes-128-cbc", Buffer.from(key), Buffer.from(iv))
|
|
519
|
+
let decrypted = decipher.update(message, "base64", "utf-8")
|
|
520
|
+
decrypted += decipher.final("utf-8")
|
|
521
|
+
return resolve(JSON.parse(decrypted))
|
|
522
|
+
}
|
|
523
|
+
/* No Auth */
|
|
524
|
+
else{
|
|
525
|
+
const decipher = crypto.createDecipheriv("aes-128-cbc", Buffer.from(pseudoEnv.process.env.RABBIT_MESSAGE_KEY), Buffer.from(pseudoEnv.process.env.RABBIT_MESSAGE_IV))
|
|
526
|
+
let decrypted = decipher.update(message, "base64", "utf-8")
|
|
527
|
+
decrypted += decipher.final("utf-8")
|
|
528
|
+
return resolve(JSON.parse(decrypted))
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
else if(mode == "no auth"){
|
|
532
|
+
/* Unchecked Token (Illegal/Refresh) */
|
|
533
|
+
if(token){
|
|
534
|
+
const {key, iv} = pipe(token)
|
|
535
|
+
.then(token=> token.split(".")[0])
|
|
536
|
+
.then(tokenBody=> this.getUserInfo({tokenBody: tokenBody}))
|
|
537
|
+
.then(({userName, userId, displayName})=>{
|
|
538
|
+
return switchPourStr(
|
|
539
|
+
userName,
|
|
540
|
+
pseudoEnv.process.env.RABBIT_MESSAGE_KEY,
|
|
541
|
+
userId,
|
|
542
|
+
pseudoEnv.process.env.RABBIT_MESSAGE_IV,
|
|
543
|
+
displayName,
|
|
544
|
+
)
|
|
545
|
+
})
|
|
546
|
+
.then(mixWord=> crypto.hash("sha256", mixWord))
|
|
547
|
+
.then(hash=>{
|
|
548
|
+
return {
|
|
549
|
+
key: hash.substring(0, 16),
|
|
550
|
+
iv: hash.substring(48)
|
|
551
|
+
}
|
|
552
|
+
})
|
|
553
|
+
.result
|
|
554
|
+
|
|
555
|
+
const decipher = crypto.createDecipheriv("aes-128-cbc", Buffer.from(key), Buffer.from(iv))
|
|
556
|
+
let decrypted = decipher.update(message, "base64", "utf-8")
|
|
557
|
+
decrypted += decipher.final("utf-8")
|
|
558
|
+
return resolve(JSON.parse(decrypted))
|
|
559
|
+
}
|
|
560
|
+
/* No Auth */
|
|
561
|
+
else{
|
|
562
|
+
const decipher = crypto.createDecipheriv("aes-128-cbc", Buffer.from(pseudoEnv.process.env.RABBIT_MESSAGE_KEY), Buffer.from(pseudoEnv.process.env.RABBIT_MESSAGE_IV))
|
|
563
|
+
let decrypted = decipher.update(message, "base64", "utf-8")
|
|
564
|
+
decrypted += decipher.final("utf-8")
|
|
565
|
+
return resolve(JSON.parse(decrypted))
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
})
|
|
569
|
+
},
|
|
570
|
+
verifyToken: function({token, userAgent}){
|
|
571
|
+
const response = new ResponseCode()
|
|
572
|
+
return new Promise(async (resolve, reject)=>{
|
|
573
|
+
try{
|
|
574
|
+
await this.publish({
|
|
575
|
+
topic: "authenthor/session/svVerifyToken",
|
|
576
|
+
mode: "no auth",
|
|
577
|
+
trip: "returning",
|
|
578
|
+
data:{
|
|
579
|
+
token: token,
|
|
580
|
+
userAgent: userAgent
|
|
581
|
+
}
|
|
582
|
+
})
|
|
583
|
+
.then(apiRes=>{
|
|
584
|
+
response.createNew(apiRes)
|
|
585
|
+
throw "abort"
|
|
586
|
+
})
|
|
587
|
+
}
|
|
588
|
+
catch(something){
|
|
589
|
+
if(something != "abort"){
|
|
590
|
+
// err: other error
|
|
591
|
+
response.pushCode("LOGIC_ERROR")
|
|
592
|
+
response.pushTrace({code: "LOGIC_ERROR", trace: `Unexpected error on ${pseudoEnv.process.env.SVC_DISPLAY} svCreateToken() function`})
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
resolve(response)
|
|
596
|
+
}
|
|
597
|
+
})
|
|
598
|
+
},
|
|
599
|
+
getUserInfo: function({tokenBody}){
|
|
600
|
+
return pipe(tokenBody)
|
|
601
|
+
.then(aes=>{
|
|
602
|
+
const decipher = crypto.createDecipheriv("aes-128-cbc", Buffer.from(pseudoEnv.process.env.TOKEN_KEY), Buffer.from(pseudoEnv.process.env.TOKEN_IV))
|
|
603
|
+
let decrypted = decipher.update(aes, "base64", "utf-8")
|
|
604
|
+
return decrypted += decipher.final("utf-8")
|
|
605
|
+
})
|
|
606
|
+
.then(json=> JSON.parse(json))
|
|
607
|
+
.then(circular=> circular.user)
|
|
608
|
+
.result // { userId, userName, displayName }
|
|
609
|
+
},
|
|
610
|
+
update: function(){
|
|
611
|
+
version.update()
|
|
612
|
+
},
|
|
613
|
+
apiVer: function(){
|
|
614
|
+
return version.deprecatedVersion()+1
|
|
615
|
+
},
|
|
616
|
+
latestVer: function(){
|
|
617
|
+
return version.latestVersion()
|
|
618
|
+
}
|
|
159
619
|
}
|